编译原理实验LL1分析

//  下面是实验三的内容 :

class LL1analysis extends JFrame implements ActionListener{

  JLabel labelGrammarInput ;
  JButton buttonOpenFile;
  JButton buttonCertainGrammar;
  JButton buttonSaveFile;

  JLabel labelWarning1;
  JLabel labelWarning2;
  JLabel labelWarning3;

  JTextArea textAreaGrammar;
  JButton buttonGenerateFirstSet;
  JButton buttonGenerateFollowSet;

  JLabel labelFirstSet;
  JLabel labelFollowSet;
  JTable textAreaFirstSet;
  JTable textAreaFollowSet;

  JLabel labelForecastAnalysisTable;
  JButton buttonGenerateForecastAnalysis;
  JTable textAreaForecastAnalysisTable;

  JLabel labelAnalysisSentence;
  JLabel labelWaitAnalosisSentence;
  JTextField textFieldWaitAnalysisSentence;
  JButton buttonAnalysis , buttonSingleStepShow , buttonOneChickDisplay;
  JLabel labelAnalysisResult ;
  JTextArea textAreaAnalysisResult;

  // 用于 实现功能的变量
  grammar currentGrammar ;

  boolean certainGrammar = false;

  boolean readyAnalysis = false;

  // 为句型 分析添加
  Stack<character> analStack = new Stack<>();
  char[] sequence;
  int analIndex;

  boolean isEnd = false;

  String law = "*()+";
  LL1analysis(){
    init();
  }

  void init(){
    labelGrammarInput = new JLabel("&#x6587;&#x6CD5;&#x8F93;&#x5165;");
    buttonOpenFile =  new JButton("&#x6253;&#x5F00;&#x6587;&#x4EF6;");
    buttonOpenFile.addActionListener(this::actionPerformed);
    buttonSaveFile = new JButton("&#x4FDD;&#x5B58;&#x6587;&#x6CD5;");
    buttonSaveFile.addActionListener(this::actionPerformed);
    buttonCertainGrammar = new JButton("&#x786E;&#x8BA4;&#x6587;&#x6CD5;");
    buttonCertainGrammar.addActionListener(this::actionPerformed);
    labelWarning1 = new JLabel("&#x6CE8;&#x610F;&#x4E8B;&#x9879;:&#x8BF7;&#x8F93;&#x5165;&#x6EE1;&#x8DB3;L(1)&#x6700;&#x7B80;&#x5224;&#x522B;&#x7684;2&#x578B;&#x6587;&#x6CD5;&#x3002;-&#x884C;&#x4E00;&#x4E2A;&#x4EA7;&#x751F;&#x5F0F;");
    labelWarning2 = new JLabel("&#x6CE8;&#x610F;&#x4E8B;&#x9879;:&#x8BF7;&#x8F93;&#x5165;&#x5F62;&#x5F0F;&#x5982;S->A&#x7684;&#x4EA7;&#x751F;&#x5F0F;&#xFF0C;&#x7A7A;&#x683C;&#x7528;_&#x8868;&#x793A;&#xFF0C;&#x7A7A;&#x7528;#&#x8868;&#x793A;");
    labelWarning3 = new JLabel("&#x6CE8;&#x610F;&#x4E8B;&#x9879;:&#x5F00;&#x59CB;&#x7B26;&#x4E3A;&#x7B2C;&#x4E00;&#x4E2A;&#x4EA7;&#x751F;&#x5F0F;&#x7684;&#x5DE6;&#x90E8;&#xFF0C;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7528;&#x5927;&#x5199;&#x5B57;&#x6BCD;&#x8868;&#x793A;");

    textAreaGrammar = new JTextArea(15,10);

    buttonGenerateFirstSet = new JButton("&#x751F;&#x6210;First&#x96C6;");
    buttonGenerateFirstSet.addActionListener(this::actionPerformed);
    buttonGenerateFollowSet = new JButton("&#x751F;&#x6210;Fllow&#x96C6;");
    buttonGenerateFollowSet.addActionListener(this::actionPerformed);

    labelFirstSet = new JLabel("First&#x96C6;");
    textAreaFirstSet = new JTable(null);
    labelFollowSet = new JLabel("Follow&#x96C6;");
    textAreaFollowSet = new JTable(null);

    labelForecastAnalysisTable = new JLabel("&#x9884;&#x6D4B;&#x5206;&#x6790;&#x8868;");
    buttonGenerateForecastAnalysis = new JButton("&#x6784;&#x9020;&#x9884;&#x6D4B;&#x5206;&#x6790;");
    buttonGenerateForecastAnalysis.addActionListener(this::actionPerformed);
    textAreaForecastAnalysisTable = new JTable(null);
    labelAnalysisSentence = new JLabel("&#x5206;&#x6790;&#x53E5;&#x5B50;");
    labelWaitAnalosisSentence = new JLabel("&#x5F85;&#x5206;&#x6790;&#x53E5;&#x5B50;");
    textFieldWaitAnalysisSentence = new JTextField(15);
    buttonAnalysis = new JButton("&#x5206;&#x6790;");

    buttonAnalysis.addActionListener(this::actionPerformed);
    buttonSingleStepShow = new JButton("&#x5355;&#x6B65;&#x663E;&#x793A;");
    buttonSingleStepShow.addActionListener(this::actionPerformed);
    buttonOneChickDisplay = new JButton("&#x4E00;&#x952E;&#x663E;&#x793A;");
    buttonOneChickDisplay.addActionListener(this::actionPerformed);

    labelAnalysisResult = new JLabel("&#x5206;&#x6790;&#x7ED3;&#x679C;");
    textAreaAnalysisResult  = new JTextArea(20,15);

    /*
    &#x6574;&#x4F53; &#x4E3A;&#x4E00;&#x4E2A;&#x4E00;&#x884C;&#x4E24;&#x5217;&#x7684;&#x7ED3;&#x6784;
    &#x7B2C;&#x4E00;&#x5217;&#xFF1A;
          &#x4E3A;&#x4E00;&#x4E2A;&#x4E24;&#x884C;&#x4E00;&#x5217;&#x7684;&#x7ED3;&#x6784;
            &#x7B2C;&#x4E00;&#x884C;&#xFF1A; &#x4E3A;&#x4E00;&#x4E2A;&#x4E94;&#x4E2A;&#x65B9;&#x5411;&#x7684;&#x7ED3;&#x6784;&#xFF1A;
                      &#x4E0A;&#x65B9;&#xFF1A; &#x4E3A;&#x4E00;&#x4E2A;&#x4E94;&#x884C;&#x4E00;&#x5217;&#x7684;&#x7ED3;&#x6784;  &#x7B2C;&#x4E8C;&#x884C;&#x7528;&#x4E00;&#x4E2A;&#x4E00;&#x884C;&#x4E09;&#x5217;&#x7684;&#x7ED3;&#x6784;&#x5305;&#x62EC;&#x4E09;&#x4E2A;&#x6309;&#x94AE;  &#x5176;&#x4F59;&#x90FD;&#x53EA;&#x6709;&#x4E00;&#x4E2A;&#x6807;&#x7B7E;
                      center &#x4E3A;&#x4E00;&#x4E2A;textarea  &#xFF1B;south &#x4E3A;&#x4E00;&#x4E2A;&#x4E00;&#x884C;&#x4E24;&#x5217;&#x7684;&#x7ED3;&#x6784;  &#x5305;&#x542B;&#x4E24;&#x4E2A;&#x6309;&#x94AE;
            &#x7B2C;&#x4E8C;&#x884C;&#xFF1A; &#x4E3A;&#x4E00;&#x4E2A;&#x56DB;&#x884C;&#x4E00;&#x5217;&#x7684;&#x7ED3;&#x6784;&#xFF1A; &#x5206;&#x522B;&#x662F;&#x4E24;&#x4E2A;&#x6807;&#x7B7E;&#x548C;&#x4E24;&#x4E2A;area
     */
    setLayout(new GridLayout(1,2));

    JPanel  panel1 = new JPanel();
    panel1.setLayout(new GridLayout(2,1));

    JPanel panel1_1 = new JPanel();
    panel1_1.setLayout(new BorderLayout());
    JPanel panel1_1_1 =  new JPanel();
    panel1_1_1.setLayout(new GridLayout(5,1));
    JPanel  panel1_1_1_1  = new JPanel();
    panel1_1_1_1.setLayout(new GridLayout(1,3));
    panel1_1_1_1.add(buttonOpenFile);
    panel1_1_1_1.add(buttonCertainGrammar);
    panel1_1_1_1.add(buttonSaveFile);
    panel1_1_1.add(labelGrammarInput);
    panel1_1_1.add(panel1_1_1_1);
    panel1_1_1.add(labelWarning1);
    panel1_1_1.add(labelWarning2);
    panel1_1_1.add(labelWarning3);
    panel1_1.add(panel1_1_1 , BorderLayout.NORTH);
    /*
    JScrollPane scroller = new JScrollPane(textAreaSourcePrograme);
    scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scroller, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;
    textAreaSourcePrograme.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
    textAreaSourcePrograme.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"
     */
    JScrollPane scrollPane1 = new JScrollPane(textAreaGrammar);
    scrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scrollPane1, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;
    textAreaGrammar.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
    textAreaGrammar.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"
    panel1_1.add(scrollPane1,BorderLayout.CENTER);
    JPanel panel1_1_2 = new JPanel();
    panel1_1_2.setLayout(new GridLayout(1,2));
    panel1_1_2.add(buttonGenerateFirstSet);
    panel1_1_2.add(buttonGenerateFollowSet);
    panel1_1.add(panel1_1_2 , BorderLayout.SOUTH);

    JPanel panel1_2 = new JPanel();
    panel1_2.setLayout(new GridLayout(2,1));
    JPanel panel1_2_1 = new JPanel();
    panel1_2_1.setLayout(new BorderLayout());
    panel1_2_1.add(labelFirstSet ,BorderLayout.NORTH );

    JScrollPane scrollPane3 = new JScrollPane(textAreaFirstSet);
    scrollPane3.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scrollPane3, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;

//    textAreaFirstSet.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
//    textAreaFirstSet.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"

    panel1_2_1.add(scrollPane3 , BorderLayout.CENTER);

    JPanel panel1_2_2 = new JPanel();
    panel1_2_2.setLayout(new BorderLayout());
    panel1_2_2.add(labelFollowSet ,BorderLayout.NORTH );
    JScrollPane scrollPane2 = new JScrollPane(textAreaFollowSet);
    scrollPane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scrollPane2, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;
//    textAreaFollowSet.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
//    textAreaFollowSet.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"
    panel1_2_2.add(scrollPane2 , BorderLayout.CENTER);

    panel1_2.add(panel1_2_1);
    panel1_2.add(panel1_2_2);

    panel1.add(panel1_1);
    panel1.add(panel1_2);

    this.add(panel1);

    /*
     &#x7B2C;&#x4E8C;&#x5217;&#xFF1A;
          &#x4E3A;&#x4E00;&#x4E2A;&#x4E94;&#x4E2A;&#x65B9;&#x5411;&#x7684;&#x7ED3;&#x6784;&#xFF1A;
                            &#x4E0A;&#x65B9;&#xFF1A; &#x7528;&#x4E09;&#x884C;&#x4E00;&#x5217;&#x7684;  &#x5305;&#x542B;  &#x6807;&#x7B7E; &#x6309;&#x94AE;  area
                            &#x4E2D;&#x95F4;  &#x7528;&#x4E00;&#x4E2A;&#x4E94;&#x4E2A;&#x65B9;&#x5411;&#x7684;&#x7ED3;&#x6784;
                                                    &#x4E0A;&#xFF1A; &#x4E00;&#x4E2A;&#x6807;&#x7B7E;
                                                    &#x4E2D;&#xFF1A; &#x4E24;&#x884C;&#x4E00;&#x5217;  &#x6807;&#x7B7E; fild
                                                    &#x4E0B;&#xFF1A;  &#x4E09;&#x884C;&#x4E00;&#x5217;  &#x4E09;&#x4E2A;&#x6309;&#x94AE;
                            &#x4E0B;&#x65B9;&#xFF1A; &#x4E24;&#x884C;&#x4E00;&#x5217;&#xFF1A; &#x6807;&#x7B7E;  area
     */

    JPanel panel2 = new JPanel();
    panel2.setLayout(new GridLayout(2,1));

    JPanel panel2_1 = new JPanel();
    panel2_1.setLayout(new BorderLayout());
    JPanel panel2_1_1 = new JPanel();
    panel2_1_1.setLayout(new GridLayout(1,2));
    panel2_1_1.add(labelForecastAnalysisTable);
    panel2_1_1.add(buttonGenerateForecastAnalysis);
    panel2_1.add(panel2_1_1 , BorderLayout.NORTH );

    JScrollPane scrollPane4 = new JScrollPane(textAreaForecastAnalysisTable);
    scrollPane4.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scrollPane4, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;
//    textAreaForecastAnalysisTable.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
//    textAreaForecastAnalysisTable.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"

    panel2_1.add(scrollPane4  , BorderLayout.CENTER);
    panel2_1.add(labelAnalysisSentence , BorderLayout.SOUTH);

    JPanel panel2_2 = new JPanel();
    panel2_2.setLayout(new BorderLayout());

//    JPanel panel2_2_1 = new JPanel();
//    panel2_2_1.setLayout(new GridLayout(2,1));
//    panel2_2_1.add(labelAnalysisSentence );

    JPanel panel2_2_2 = new JPanel();
    panel2_2_2.setLayout(new  BorderLayout());
    panel2_2_2.add(labelWaitAnalosisSentence ,BorderLayout.WEST);
    panel2_2_2.add(textFieldWaitAnalysisSentence , BorderLayout.CENTER);

    JPanel panel2_2_3 = new JPanel();
    panel2_2_3.setLayout(new GridLayout(1,3));
    panel2_2_3.add(buttonAnalysis);
    panel2_2_3.add(buttonSingleStepShow);
    panel2_2_3.add(buttonOneChickDisplay);

//    panel2_2.add(panel2_2_1 , BorderLayout.NORTH);
    panel2_2.add(panel2_2_2  , BorderLayout.CENTER);
    panel2_2.add(panel2_2_3  , BorderLayout.SOUTH);

    JPanel panel2_3 = new JPanel();
    panel2_3.setLayout(new BorderLayout());
    panel2_3.add(labelAnalysisResult , BorderLayout.NORTH);

    JScrollPane scrollPane5 = new JScrollPane(textAreaAnalysisResult);
    scrollPane5.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    panel1.add(scrollPane5, BorderLayout.CENTER);//&#x5411;&#x7A97;&#x53E3;&#x6DFB;&#x52A0;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;
    textAreaAnalysisResult.setWrapStyleWord(true);//&#x8BBE;&#x7F6E;&#x5355;&#x8BCD;&#x5728;&#x4E00;&#x884C;&#x4E0D;&#x8DB3;&#x5BB9;&#x7EB3;&#x65F6;&#x6362;&#x884C;
    textAreaAnalysisResult.setLineWrap(true);//&#x8BBE;&#x7F6E;&#x6587;&#x672C;&#x7F16;&#x8F91;&#x533A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#x9ED8;&#x8BA4;&#x4E3A;true,&#x5373;&#x4F1A;"&#x81EA;&#x52A8;&#x6362;&#x884C;"
    panel2_3.add(scrollPane5 , BorderLayout.CENTER);

    JPanel t = new JPanel();
    t.setLayout(new BorderLayout());
    t.add(panel2_2 , BorderLayout.NORTH);
    t.add(panel2_3 , BorderLayout.CENTER);
    panel2.add(panel2_1 );
    panel2.add(t );
//    panel2.add(panel2_3 );

    this.add(panel2);

    //&#x8BBE;&#x7F6E;&#x7A97;&#x53E3;&#x5728;&#x5C4F;&#x5E55;&#x4E0A;&#x7684;&#x4F4D;&#x7F6E;&#x3001;&#x5927;&#x5C0F;&#x548C;&#x53EF;&#x89C1;&#x6027;
    this.setLocation(100, 100);
    this.setSize(1000, 700);
    this.setVisible(true);
//    addWindowListener(new WindowAdapter() {
//      public void windowClosing(WindowEvent e) {
//        exitWindowChoose();
//      }
//    });
    this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//&#x4F7F;&#x7528; System exit &#x65B9;&#x6CD5;&#x9000;&#x51FA;&#x5E94;&#x7528;&#x7A0B;&#x5E8F;

//      &#x6D4B;&#x8BD5;&#x4E13;&#x7528;&#xFF1A;
    textAreaGrammar.setText("S->AB\n"
        + "S->bC\n"+"C->AD\n"+"C->b\nA->#\nA->b\nD->aS\nD->c\nB->#\nB->aD");

    buttonCertainGrammar.doClick();

//    textAreaGrammar.setText("E->TR\n"
//        + "R->+TR\n"
//        + "R->#\n"
//        + "T->TY\n"
//        + "Y->*FY\n"
//        + "Y->#\n"
//        + "F->(E)\n"
//        + "F->a");
//
//    buttonCertainGrammar.doClick();

    /*
    E->TR
R->+TR
R->#
T->TY
Y->*FY
Y->#
F->(E)
F->a
     */
  }

  boolean certainGrammar(){

    if (currentGrammar !=null){
      return currentGrammar.isL1L();
    }

    return  false;
  }

  @Override
  public void actionPerformed(ActionEvent e) {

    if (e.getSource() == buttonCertainGrammar){
      initGrammar();
      if (certainGrammar() ){
        JOptionPane.showMessageDialog(null, "&#x5408;&#x6CD5;", "&#x5224;&#x65AD;&#x7ED3;&#x679C;", JOptionPane.ERROR_MESSAGE);
      }else {
        JOptionPane.showMessageDialog(null, "&#x4E0D;&#x5408;&#x6CD5;", "&#x5224;&#x65AD;&#x7ED3;&#x679C;", JOptionPane.ERROR_MESSAGE);
        currentGrammar = null;
      }
//      currentGrammar.show(textAreaFirstSet);

    }else if(e.getSource() == buttonGenerateFirstSet){
      // &#x751F;&#x6210;First&#x96C6;
      if (currentGrammar !=null){
        currentGrammar.showFirstSet(textAreaFirstSet);
      }

    }else if (e.getSource() == buttonGenerateFollowSet){
      if (currentGrammar !=null){
        currentGrammar.showFollowSet(textAreaFollowSet);
      }
    }else if (e.getSource() == buttonGenerateForecastAnalysis){
      // &#x663E;&#x793A;  &#x6784;&#x9020; &#x9884;&#x6D4B;&#x5206;&#x6790;&#x8868;
      if (currentGrammar !=null){
        currentGrammar.showGenerateForecastTable(textAreaForecastAnalysisTable);
      }else {
        currentGrammar.generateForecastTable();
      }
    }else if (e.getSource() == buttonAnalysis){
      initAnalysis();
      if (readyAnalysis == false){
        textAreaAnalysisResult.append("&#x65E0;&#x6CD5;&#x542F;&#x52A8;"+ "\n");
      }else {
        textAreaAnalysisResult.setText("");
        startAnalysis();
        textAreaAnalysisResult.append("&#x51C6;&#x5907;&#x5B8C;&#x6BD5;"+ "\n");

      }

    }else if (e.getSource() == buttonOneChickDisplay) {
      while (isEnd == false){
        oneStep();
      }
    }else if (e.getSource() == buttonSingleStepShow){
      oneStep();
    }else if (e.getSource() == buttonOpenFile){
      String ass = openGrammar();
      if (ass !=null){
        textAreaGrammar.setText("");
        textAreaGrammar.append(ass);
      }else {
        textAreaGrammar.append("&#x9519;&#x8BEF;");
      }
    }if (e.getSource() == buttonSaveFile){
      save();
    }

  }

  String openGrammar() {
    String str = null;
    JFileChooser fileChooser = new JFileChooser();
    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
    fileChooser.setDialogTitle("&#x6253;&#x5F00;&#x6587;&#x4EF6;");
    int result = fileChooser.showOpenDialog(this);
    if (result == JFileChooser.CANCEL_OPTION) {
      return null;
    }
    File fileName = fileChooser.getSelectedFile();
    if (fileName == null || fileName.getName().equals("")) {
      JOptionPane.showMessageDialog(this, "&#x4E0D;&#x5408;&#x6CD5;&#x7684;&#x6587;&#x4EF6;&#x540D;", "&#x4E0D;&#x5408;&#x6CD5;&#x7684;&#x6587;&#x4EF6;&#x540D;", JOptionPane.ERROR_MESSAGE);
    } else {
      try {

        FileInputStream fis = new FileInputStream(fileName);
        InputStreamReader isr = new InputStreamReader(fis, "gbk");//&#x907F;&#x514D;&#x4E2D;&#x6587;&#x4E71;&#x7801;
        BufferedReader bfr = new BufferedReader(isr);

//        FileReader fr = new FileReader(fileName);
//        BufferedReader bfr = new BufferedReader(fr);
        String ans = "";
        int count = 0;
        if ((str = bfr.readLine()) != null) {
          count = 1;
        }
        while (count != 0) {
//          System.out.print(str);
          ans = ans.concat(str) + "\n";
          if ((str = bfr.readLine()) != null) {
            count = 1;
//            System.out.print("\n");
          } else {
            count = 0;
          }
        }

        return ans;
      } catch (Exception e) {

      }

    }
    return null;
  }

  void save( ){
    String str = null;
    JFileChooser fileChooser = new JFileChooser();
    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
    //fileChooser.setApproveButtonText("&#x786E;&#x5B9A;");
    fileChooser.setDialogTitle("&#x4FDD;&#x5B58;");
    int result = fileChooser.showSaveDialog(this);
    File saveFileName = fileChooser.getSelectedFile();
    if (saveFileName == null || saveFileName.getName().equals("")) {
      JOptionPane.showMessageDialog(this, "&#x4E0D;&#x5408;&#x6CD5;&#x7684;&#x6587;&#x4EF6;&#x540D;", "&#x4E0D;&#x5408;&#x6CD5;&#x7684;&#x6587;&#x4EF6;&#x540D;", JOptionPane.ERROR_MESSAGE);
    } else {
      try {
        FileWriter fw = new FileWriter(saveFileName);
        BufferedWriter bfw = new BufferedWriter(fw);
        String ans = textAreaGrammar.getText();
        bfw.write(ans);
        bfw.flush();//&#x5237;&#x65B0;&#x8BE5;&#x6D41;&#x7684;&#x7F13;&#x51B2;
        bfw.close();
      } catch (IOException ioException) {
      }
    }
  }

  void oneStep(){
    // &#x5F80;&#x524D;&#x5206;&#x6790;&#x4E00;&#x6B65;
    if (analIndex == sequence.length){
      isEnd  =true;
      textAreaAnalysisResult.append("&#x5206;&#x6790;&#x7ED3;&#x675F; &#x53E5;&#x5B50;&#x5408;&#x6CD5; \n");
      return;
    }

    char sour = analStack.peek();
    char des = sequence[analIndex];
    if (sour == des){
      analIndex++;
      analStack.pop();
      textAreaAnalysisResult.append("&#x5339;&#x914D;" + sour + "\n");
      textAreaAnalysisResult.append("&#x5F53;&#x524D;&#x53E5;&#x5B50;" + String.valueOf(sequence).substring(analIndex)+ "\n");
      textAreaAnalysisResult.append("&#x5F53;&#x524D;&#x5206;&#x6790;&#x6808;" + analStack.toString()+ "\n");
      textAreaAnalysisResult.append("\n\n");
      return;
    }
    Map<character , punit> now = currentGrammar.forecastAnalysisTable.get(new Character(sour));

    if (now == null){
      textAreaAnalysisResult.append("&#x51FA;&#x9519;"+ "&#x662F;&#x5408;&#x6CD5;&#x53E5;&#x5B50;  \n");
      isEnd = true;
      return;
    }
    pUnit ans = now.get(new Character(des));
    if (ans == null){
      textAreaAnalysisResult.append("&#x51FA;&#x9519;"+ "&#x662F;&#x5408;&#x6CD5;&#x53E5;&#x5B50;  \n");
      isEnd = true;
      return;
    }

    textAreaAnalysisResult.append("&#x5339;&#x914D;&#x4EA7;&#x751F;&#x5F0F;"+ans.toString()+ "\n");
    analStack.pop();
    String  lll = ans.des;
    char[] lis = lll.toCharArray();
    int len = lis.length;
    int i = len-1;
    for (;i>=0 ; i--){
      if (lis[i] == '#'){
        break;
      }
      analStack.push(new Character(lis[i]));
    }

    textAreaAnalysisResult.append("&#x5F53;&#x524D;&#x53E5;&#x5B50;" + String.valueOf(sequence).substring(analIndex)+ "\n");
    textAreaAnalysisResult.append("&#x5F53;&#x524D;&#x5206;&#x6790;&#x6808;" + analStack.toString()+ "\n");
    textAreaAnalysisResult.append("\n\n");

  }

  void initAnalysis(){
    if (currentGrammar == null || currentGrammar.forecastAnalysisTable == null){
      readyAnalysis = false;
    }else {
      readyAnalysis = true;
    }

  }

  void startAnalysis(){
    // &#x542F;&#x52A8; &#x5206;&#x6790;
    String a = textFieldWaitAnalysisSentence.getText();
    a = a+"#";
    sequence = a.toCharArray();
    analIndex = 0;
    analStack.clear();
    analStack.push(new Character(new Character('#')));
    analStack.push(new Character(currentGrammar.S));
    isEnd = false;

  }

  void initGrammar(){
    String text = textAreaGrammar.getText();
    initGrammar(text);

  }

  void initGrammar(String text){
    String[] gra = text.split("\n");

    // &#x6839;&#x636E; &#x8F93;&#x5165;&#x7684;&#x4EA7;&#x751F;&#x5F0F;  &#x521D;&#x59CB;&#x5316; &#x6587;&#x6CD5;
    // &#x5148;&#x7EDF;&#x8BA1; &#x7EC8;&#x7ED3;&#x7B26; &#x548C;  &#x975E;&#x7EC8;&#x7ED3;&#x7B26;

    grammar ans = new grammar();

    Set<character> VN  = new HashSet<>();
    Set<character> VT  = new HashSet<>();
    char[] all = text.toCharArray();
    // &#x5148;&#x5355;&#x72EC;&#x62BD;&#x51FA; S
    ans.S = all[0];
    for (char a : all){
      if (isBigLetter(a)){
        VN.add(new Character(a));
      }

      if (isSmallLetter(a)){
        VT.add(new Character(a));
      }
    }

    // &#x5C06;&#x96C6;&#x5408; &#x8F6C;&#x6362;&#x4E3A;&#x6570;&#x7EC4;   &#x521D;&#x59CB;&#x5316;  VN &#x548C;VT
    ans.VN = setToCharArray(VN);
    ans.VT = setToCharArray(VT);
//    System.out.println(VN);
//    System.out.println(VT);

    // &#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;  &#x975E;&#x7EC8;&#x7ED3;&#x7B26; &#x5230;&#x4E0B;&#x6807;&#x7684;&#x6620;&#x5C04;
    Map<character , integer> indexMap = new HashMap<>();
    int i=0;
    for (Character a : VN){
      indexMap.put(a , new Integer(i++));
    }

    // &#x4E0B;&#x9762;  &#x6839;&#x636E;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;&#x6570;&#x91CF;   &#x521D;&#x59CB;&#x5316;P  &#x7136;&#x540E;&#x904D;&#x5386;&#x6587;&#x6CD5;  &#x6DFB;&#x52A0;&#x4EA7;&#x751F;&#x5F0F;
    ans.P = new ArrayList[VN.size()];
    for (i=0 ; i<vn.size() ; i++){ ans.p[i]="new" arraylist<>();
    }

    // &#x4E0B;&#x9762;  &#x904D;&#x5386; &#x6DFB;&#x52A0;
    for (String now : gra){
      // &#x6BCF;&#x4E00;&#x884C; &#x662F;&#x4E00;&#x4E2A;&#x4EA7;&#x751F;&#x5F0F;
      now= now.replaceAll(" ","");
      char[] arr = now.toCharArray();
      char source = arr[0];
      String des = now.substring(3);
      pUnit  x = new pUnit(String.valueOf(source) , des);
      ans.P[ indexMap.get(source) ].add(x);

    }

    // &#x521D;&#x59CB;&#x5316;&#x5B8C;&#x6210;
//    System.out.println("&#x521D;&#x59CB;&#x5316;&#x7ED3;&#x679C;");
//    System.out.println(ans.P);

    currentGrammar = ans;

//    currentGrammar.show();

  }

  //  &#x5224;&#x65AD; &#x662F;&#x5927;&#x5199;&#x5B57;&#x6BCD; &#x8FD8;&#x662F;&#x5C0F;&#x5199;&#x5B57;&#x6BCD;
  boolean isBigLetter( char a){
    if (a >= 'A' && a<='z') { return true; } false; boolean issmallletter( char a ){ if (a>= 'a' && a<='z') { return true; } if (law.indexof(string.valueof(a)) !="-1){" false; public char[] settochararray(set<character> a){
    char[] ans = new char[a.size()];
    int inde = 0;
    for (Character s: a){
      ans[inde++] = s;
    }

    return ans;
  }

}

// &#x6587;&#x6CD5;&#x7C7B;
class grammar{

  char[] VN ;
  char[] VT;
  ArrayList<punit>[] P; // P[i]  &#x4EE5;VN[i] &#x5F00;&#x5934;

  static int UNKNOWN = -1;
  static int YES = 1;
  static int NO = 0;
  private Map<character , set<character>>  firstSet = null;
  private boolean[] isIntroductionEmpty  = null;

  private Map<character , set<character>>  followSet = null;
  private Map<string , set<character>>   selectSet = null;

  Map<character , map<character punit>> forecastAnalysisTable= null;
  char S;

  boolean searchFirstSet(char left , char destination) {
    Set<character> des  = firstSet.get(new Character(left));

    if (des != null){
//      System.out.println(left);
//      System.out.println(des);
      return des.contains(new Character(destination));
    }

    return false;
  }

  boolean searchFollowtSet(char left , char destination){
    Set<character> des  = followSet.get(new Character(left));

    if (des != null){
      return des.contains(new Character(destination));
    }

    return false;
  }

  String searchForecasAT(char nEndChar , char currenChar){
    Map<character , punit> des  = forecastAnalysisTable.get(new Character(nEndChar));

    if (des != null){
      return des.get(new Character(currenChar)).toString();
    }

    return  null;
  }

  void showGenerateForecastTable(JTable panel){
    if (forecastAnalysisTable == null){
      generateForecastTable();
    }
    int len1 = VN.length;
    int len2 = VT.length+1;
    String[] anfd = new String[len2];
    int i , j;
    anfd[0] = new String("\\");
    for (i=1 ; i<len2 ; i++){ anfd[i]="String.valueOf(VT[i-1]);" } tablemodel model="new" defaulttablemodel(anfd , len2); tablecolumnmodel columnmodel="new" defaulttablecolumnmodel(); tablecolumn tablecolumn(); panel.setcolumnmodel(columnmodel); panel.setmodel(model); for (i="0" i< len1 i++ ){ model.setvalueat(string.valueof(vn[i]) i 0); (j="1" j<len2 j++){ model.setvalueat(string.valueof( searchforecasat(vn[i] vt[j-1]) ) j); panel.settext(""); set<character> VT = arrToSet(this.VT);
//    VT.add(new Character('#'));
//    for (char a : VN){
//      System.out.print(a + ": \n");
//
//      Map<character , punit> now = forecastAnalysisTable.get(new Character(a));
//      for (char s : VT){
//        if (now.containsKey(new Character(s))){
//          // &#x5305;&#x542B;
//          System.out.print("  "+String.valueOf(s) + "   ");
//          System.out.print( now.get(new Character(s)).toString() + "\n");
//        }else {
//          System.out.print("  "+String.valueOf(s) + "   null" + "\n");
//        }
//
//
//      }
//
//    }

  }

  boolean isL1L(){
    if (selectSet == null){
      getSelectSet();
    }

    // &#x5224;&#x65AD;&#x662F;&#x4E0D;&#x662F;  LL1

    int i=0;
    for (ArrayList<punit> a : P){
      // &#x7B2C;i&#x4E2A;&#x7684;&#x6240;&#x6709;&#x4EA7;&#x751F;&#x5F0F;
      int count = 0;
      Set<character> sc = new HashSet<>();
      for (pUnit b : a){
        if (selectSet.containsKey(b.toString())){
          Set<character> now = selectSet.get(b.toString());
          sc.addAll(now);
          count += now.size();
        }

      }

      if (count != sc.size()){
        return false;
      }
      i++;
    }

    return true;
  }

  void generateForecastTable(){

    if (selectSet == null){
      getSelectSet();
    }

    if (forecastAnalysisTable != null){
      return;
    }

    Map<character , map<character punit>> table =  new HashMap<>();

    int i=0;
    for (ArrayList<punit> a : P){
      // &#x7B2C;i&#x4E2A;&#x7684;&#x6240;&#x6709;&#x4EA7;&#x751F;&#x5F0F;
      Map<character , punit> k = new HashMap<>();
      for (pUnit b : a){
        Set<character> no = selectSet.get(b.toString());
        for(char ass : no){
          k.put(new Character(ass) , b);
        }
      }
      table.put( new Character(VN[i]) , k );
      i++;
    }

    this.forecastAnalysisTable  = table;

  }

  void showFirstSet(JTable panel){
    // &#x663E;&#x793A;  first&#x96C6;
    int len1 = VN.length;
    int len2 = VT.length+1;
    String[] anfd = new String[len2];
    int i , j;
    anfd[0] = new String("\\");
    for (i=1 ; i<len2 ; i++){ anfd[i]="String.valueOf(VT[i-1]);" } tablemodel model="new" defaulttablemodel(anfd , len2); tablecolumnmodel columnmodel="new" defaulttablecolumnmodel(); tablecolumn tablecolumn(); panel.setcolumnmodel(columnmodel); panel.setmodel(model); for (i="0" i< len1 i++ ){ model.setvalueat(string.valueof(vn[i]) i 0); (j="1" j<len2 j++){ model.setvalueat(string.valueof( searchfirstset(vn[i] vt[j-1]) ) j); panel.settext(""); map<character set<character>> ans = getFirstSet();
//    System.out.print("&#x663E;&#x793A; &#x5404;&#x7EC8;&#x7ED3;&#x7B26;/&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;first&#x96C6;&#x5408;  \n");
//    System.out.print("\n");
//    System.out.print(ans.toString());
//
//
//    System.out.print("&#x663E;&#x793A; &#x5404;&#x4EA7;&#x751F;&#x5F0F;&#x7684;first&#x96C6;&#x5408;  \n");
//    for (ArrayList<punit> a : P){
//      for (pUnit b : a){
//        System.out.print(b.toString() + "  ");
//
//
//
////         &#x8FD9;&#x91CC;&#x5C55;&#x793A;&#x5404;&#x4EA7;&#x751F;&#x5F0F;&#x7684;&#x53F3;&#x90E8;&#x7B26;&#x53F7;&#x4E32;&#x7684;first&#x96C6;&#x5408;
//        System.out.print(getFirstSet(b).toString() + "\n");
////        System.out.println(b.toString());
//
//      }
//    }

  }

  void showFollowSet(JTable panel){
    int len1 = VN.length;
    int len2 = VT.length+1;
    String[] anfd = new String[len2];
    int i , j;
    anfd[0] = new String("\\");
    for (i=1 ; i<len2 ; i++){ anfd[i]="String.valueOf(VT[i-1]);" } tablemodel model="new" defaulttablemodel(anfd , len2); tablecolumnmodel columnmodel="new" defaulttablecolumnmodel(); tablecolumn tablecolumn(); panel.setcolumnmodel(columnmodel); panel.setmodel(model); for (i="0" i< len1 i++ ){ model.setvalueat(string.valueof(vn[i]) i 0); (j="1" j<len2 j++){ model.setvalueat(string.valueof( searchfollowtset(vn[i] vt[j-1]) ) j); panel.settext(""); map<character set<character>> an = getFollowSet();
//    panel.append("&#x663E;&#x793A; follow&#x96C6;&#x5408;  \n");
//    panel.append("\n");
//    panel.append(an.toString());
  }

  public grammar() {
//    P = new ArrayLis
  }

  void show(JTextArea panel){

    panel.setText("");
    for (ArrayList<punit> a : P){
      for (pUnit b : a){
        panel.append(b.toString() + "  ");

//         &#x8FD9;&#x91CC;&#x5C55;&#x793A;&#x5404;&#x4EA7;&#x751F;&#x5F0F;&#x7684;&#x53F3;&#x90E8;&#x7B26;&#x53F7;&#x4E32;&#x7684;first&#x96C6;&#x5408;
        panel.append(getFirstSet(b).toString() + "\n");
//        System.out.println(b.toString());

      }
    }

    // &#x663E;&#x793A; first&#x96C6;&#x5408;

//     &#x8FD9;&#x91CC;&#x5C55;&#x793A;  first&#x96C6;&#x5408;
    Map<character , set<character>> ans = getFirstSet();
    panel.append("&#x663E;&#x793A; first&#x96C6;&#x5408;  \n");
    panel.append("\n\n");
    panel.append(ans.toString());

    //     &#x8FD9;&#x91CC;&#x5C55;&#x793A;  follow&#x96C6;&#x5408;
    Map<character , set<character>> an = getFollowSet();
    panel.append("&#x663E;&#x793A; follow&#x96C6;&#x5408;  \n");
    panel.append("\n\n");
    panel.append(an.toString());

    panel.append("\n&#x663E;&#x793A; select&#x96C6;\n");
    for (ArrayList<punit> a : P){
      for (pUnit b : a){
        panel.append(b.toString() + "  ");

//         &#x8FD9;&#x91CC;&#x5C55;&#x793A;&#x5404;&#x4EA7;&#x751F;&#x5F0F;&#x7684;&#x53F3;&#x90E8;&#x7B26;&#x53F7;&#x4E32;&#x7684;first&#x96C6;&#x5408;
        panel.append(getSelectSet(b).toString() + "\n");
//        System.out.println(b.toString());

      }
    }

  }

  void show(){

    System.out.println(VT);
    System.out.println(VN);
    for (ArrayList<punit> a : P){
      for (pUnit b : a){
        System.out.print(b.toString() + "\n");
//        System.out.println(b.toString());

      }
    }

  }

  public grammar(char[] VN, char[] VT, ArrayList<punit>[] p, char s) {

    this.VN = VN;
    this.VT = VT;
    P = p;
    S = s;
  }

  void add( char source , String des ){
    int x = String.valueOf(VN).charAt(source);
    pUnit a = new pUnit(source , des);
    P[x].add(a);
  }

  boolean[] getIsIntroductionEmpty(){
    if (isIntroductionEmpty !=null){
      return isIntroductionEmpty;
    }
    int[] ans = new int[VN.length];
    boolean[] aans = new boolean[VN.length];

    int i;
    int l = VN.length;
    for (i=0 ; i<l 0 ; i++){ ans[i]="UNKNOWN;" } grammar now="this.copy();" 删除右部含有非终结符的产生式 int j; for (i="0" i<l (j="0" j<now.p[i].size() j++){ punit s="now.P[i].get(j);" if (s.desisempty()){ system.out.println("fdsv"); now.p[i].clear(); system.out.println("sd----"); (s.descontainendchar(vt)){ now.p[i].remove(j); (now.p[i].size()="=" && unknown){ now.show(); 重复扫描 count="1;" while (count="=1){" system.out.println(i); system.out.println(s.tostring()); system.out.print(s.des); system.out.println("ds"); break; z; (z="0" z<l z++){ (ans[z]="=" yes){ s.des="s.des.replaceAll(String.valueOf(VN[z])" , ""); (ans[i]="=" aans[i]="true;" }else { system.out.println(aans[i]); isintroductionempty="aans;" return aans; copy(){ ans="new" grammar(); ans.vn="String.valueOf(this.VN).toCharArray();" ans.vt="String.valueOf(this.VT).toCharArray();" ans.s="this.S;" ans.p="new" arraylist[vn.length]; i; l="VN.length;" ans.p[i]="new" arraylist<>();
      for (pUnit a:this.P[i] ){
        ans.P[i].add(new pUnit(a));
      }
    }

//    ans.show();

    return ans;

  }

  //  &#x8BA1;&#x7B97; &#x6BCF;&#x4E00;&#x4E2A;&#x6587;&#x6CD5;&#x7B26;&#x53F7;&#x7684; first&#x96C6;
  Map<character , set<character>> getFirstSet() {
    if (firstSet !=null){
      return firstSet;
    }

    boolean[] isToEmpty = getIsIntroductionEmpty();
//    for (boolean a : isToEmpty){
//      System.out.println(a);
//    }

//    System.out.println(VT);
//    System.out.println(VN);

    Map<character , integer> indexMap = new HashMap<>();
    int i = 0;
//    for (char a :VT){
//      indexMap.put(new Character(a) , i++);
//    }
    for (char a :VN){
      indexMap.put(new Character(a) , i++);
    }

    Map<character , set<character>> ans = new HashMap<>();

    // &#x5148;&#x7EDF;&#x8BA1;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;first&#x96C6;
    for (char a : VT){
      Set<character> x = new HashSet<>();
      x.add(new Character(a));
      ans.put(new Character(a) , x);
    }

    for (char a : VN){
      Set<character> x = new HashSet<>();
      ans.put(new Character(a) , x);
    }

    int count = 1;

    Set<character> VNSet = arrToSet(VN);
    Set<character> VTSet = arrToSet(VT);

    // &#x8FD9;&#x91CC;&#x7EDF;&#x8BA1;&#x4E00;&#x4E2A; &#x53EF;&#x4EE5;&#x63A8;&#x51FA;&#x7A7A;&#x7684;&#x96C6;&#x5408;  &#x7528;&#x4E8E;&#x540E;&#x9762;&#x5224;&#x65AD;
    Set<character> toEmpty = new HashSet<>();

    for (i=0 ; i< VN.length ; i++){
      if (isToEmpty[i]){
        toEmpty.add(new Character(VN[i]));
      }
    }

    int  j;

    while (count == 1){
      count = 0;

      // &#x6267;&#x884C;&#x7B2C;&#x4E8C;&#x6B65;   &#x82E5;X&#x2208;VN,&#x4E14;&#x6709;X&#xF0AE;a&#x2026;,a&#x2208; VT,&#x5219;a&#x2208;FIRST(X);   &#x7B2C;&#x4E09;&#x6B65; &#x82E5;X&#x2208;VN&#xFF0C;X&#xF0AE; &#x3B5; ,&#x5219;&#x3B5;&#x2208; FIRST(X);
      // &#x904D;&#x5386; &#x4EA7;&#x751F;&#x5F0F;    X&#x5FC5;&#x5B9A;&#x5C5E;&#x4E8E;VN   &#x770B;&#x53F3;&#x8FB9;  &#x662F;&#x5426; &#x90FD;&#x662F;&#x7EC8;&#x7ED3;&#x7B26;
      i=0;
      for (ArrayList<punit> now : P){
        for (pUnit x : now){
          // &#x5F53;&#x524D; &#x4E3A;&#x7B2C;i&#x4E2A;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;&#x4EA7;&#x751F;&#x5F0F;
          Set<character> cu = arrToSet(x.des.toCharArray());
          // &#x662F;&#x5426; &#x5168;&#x4E3A; &#x7EC8;&#x7ED3;&#x7B26;   &#x7B2C;&#x4E8C;&#x6B65;
//          System.out.println(cu);
//          System.out.println(VT);
          if (VTSet.containsAll(cu) && ans.get(VN[i]).contains(new Character( x.des.charAt(0) )) == false){// &#x7B26;&#x5408;&#x4E14;&#x672A;&#x5305;&#x542B;
            // &#x5168;&#x90E8;&#x5305;&#x542B;  &#x5373;&#x5168;&#x4E3A;&#x7EC8;&#x7ED3;&#x7B26;
//            System.out.println(" &#x7B2C;&#x4E8C;&#x6B65; ");
            ans.get(VN[i]).add(new Character( x.des.charAt(0) ));
//            System.out.println(VTSet);
//            System.out.println(x.des.charAt(0));
            count = 1;
//            System.out.println("sdjk");
          }

          // &#x987A;&#x4FBF;&#x5224;&#x65AD; &#x7B2C;&#x4E09;&#x6B65;
          if ( isToEmpty[i] == true  && ans.get(VN[i]).contains(new Character('#')) == false){
            // &#x8BE5;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;  &#x53EF;&#x4EE5;&#x63A8;&#x51FA;&#x7A7A;
            ans.get(VN[i]).add(new Character( '#'));
//            System.out.println("fds");
            count = 1;
          }
        }
        i++;

      }

      // &#x6267;&#x884C; &#x7B2C;&#x56DB;&#x6B65;&#x548C;&#x7B2C;&#x4E94;&#x6B65;  4)&#x82E5;X&#x2208;VN&#xFF0C;Y1,Y2,&#x2026;,Yn&#x90FD;&#x2208;VN&#xFF0C;&#x4E14;&#x6709;X&#xF0AE;Y1Y2&#x2026;Yn &#x3002;&#x5F53;Y1,Y2,&#x2026;,Yi-1&#x90FD;      &#x3B5;&#x65F6;&#xFF0C;&#xFF08;&#x5176;&#x4E2D;1<=i<=n),则first(y1)-{ε}, first(y2)-{ε},...,first(yi-1)-{ε},first(yi)都包含在first(x)中。 都是 非终结符 i="0;" for (arraylist<punit> now : P){
        // &#x7EDF;&#x8BA1;&#x8981;&#x6DFB;&#x52A0;&#x7684;&#x6240;&#x6709;&#x65B0;&#x7684; &#x5143;&#x7D20; &#x4EE5;&#x5224;&#x65AD;&#x662F;&#x5426; &#x6709;&#x65B0;&#x7684;&#x6DFB;&#x52A0;&#x8FDB;&#x53BB;

        Set<character> updateSet = new HashSet<>();// &#x8981;&#x6DFB;&#x52A0;&#x7684;    &#x6700;&#x540E;&#x5224;&#x65AD; &#x662F;&#x5426;&#x6709;&#x65B0;&#x7684;
        for (pUnit x : now){
          // &#x5F53;&#x524D; &#x4E3A;&#x7B2C;i&#x4E2A;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;&#x4EA7;&#x751F;&#x5F0F;
          Set<character> cu = arrToSet(x.des.toCharArray());
          // &#x662F;&#x5426; &#x5168;&#x4E3A; &#x975E;&#x7EC8;&#x7ED3;&#x7B26;   &#x7B2C;&#x56DB;&#x6B65;
          if (VNSet.containsAll(cu)) {
            // &#x5168;&#x90E8;&#x5305;&#x542B;  &#x5373;&#x5168;&#x4E3A;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;

            // &#x5224;&#x65AD;  &#x7B2C;&#x56DB;&#x6B65; &#x8FD8;&#x662F; &#x7B2C;&#x4E94;&#x6B65;   &#x5373;&#xFF1A; -> &#x662F;&#x5426; &#x5168;&#x90FD;&#x53EF;&#x4EE5;&#x63A8;&#x51FA;&#x7A7A;
            if (toEmpty.containsAll(cu)){
              // &#x5168;&#x90FD;&#x53EF;&#x4EE5;&#x63A8;&#x51FA;&#x7A7A;   &#x7B2C;&#x4E94;&#x6B65;
              // &#x66F4;&#x65B0; updateSet
              for (Character aa : cu){
                for (Character as : ans.get(aa)){
                  if (as !='#'){
                    updateSet.add(as);
                  }
                }
              }

              updateSet.add(new Character('#'));
              // &#x7B2C;&#x4E94;&#x6B65;

            }else {
              // &#x975E; &#x5168;&#x90FD;&#x53EF;&#x4EE5;&#x63A8;&#x51FA;&#x7A7A;   &#x7B2C;&#x56DB;&#x6B65;

              char[] curr = x.des.toCharArray();
              for (int ii = 0 ; ii < curr.length ; ii++){
                if (toEmpty.contains(curr[ii])){
                  // &#x5C5E;&#x4E8E; 0-(i-1)
                  if (updateSet.contains(new Character('#'))){
                    updateSet.addAll(ans.get(curr[ii]));
                  }else {
                    updateSet.addAll(ans.get(curr[ii]));
                    updateSet.remove(new Character('#'));
                  }
                }else {
                  // &#x5C5E;&#x4E8E; i
                  updateSet.addAll(ans.get(curr[ii]));
                  break;
                }
              }

            }

            // ok

          }else {

            // &#x8FD9;&#x91CC;&#x5C31;&#x662F;  &#x542B;&#x6709; &#x975E;&#x7EC8;&#x7ED3;&#x7B26;  &#x4E5F;&#x6709; &#x7EC8;&#x7ED3;&#x7B26;
            char[] akd = x.des.toCharArray();
            for ( char ds : akd){
              // &#x975E;&#x7EC8;&#x7ED3;&#x7B26;
              if (VNSet.contains(new Character(ds))){
                if (ans.get(ds).contains('#')){
                  //&#x53EF;&#x4EE5;&#x9000;&#x7A7A;
                  if (updateSet.contains('#')){
                    updateSet.addAll(ans.get(ds));
                  }else {
                    updateSet.addAll(ans.get(ds));
                    updateSet.remove('#');
                  }
                  continue;
                }else {
                  updateSet.addAll(ans.get(ds));
                  break;
                }
              }

              if (VTSet.contains(ds)){
                updateSet.add(new Character(ds));
                break;
              }

            }

          }

        }
        // &#x8FD9;&#x91CC;&#x904D;&#x5386;&#x5B8C; &#x7B2C;i&#x7684;&#x4E2A;&#x975E;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;&#x6240;&#x6709;&#x4EA7;&#x751F;&#x5F0F;   &#x5224;&#x65AD; &#x662F;&#x5426;&#x6709;&#x66F4;&#x65B0;

        if (ans.get(new Character(VN[i])).containsAll(updateSet)){
          // &#x5305;&#x542B;&#x5168;&#x90E8;
        }else {
          count = 1;
          ans.get(new Character(VN[i])).addAll(updateSet);
          // &#x66F4;&#x65B0;
        }

        i++;
      }

//      System.out.println(ans.toString());

    }
    firstSet = ans;
    return ans;
  }

  public Set<character>  arrToSet(char[] a){
    Set<character> ans = new HashSet<>();

    for (char as : a){
      ans.add(new Character(as));
    }
    return ans;
  }

  Set<character> getFirstSet(pUnit a){
    if (firstSet == null){
      getFirstSet();
    }
    //first&#x96C6;&#x672A;&#x521D;&#x59CB;&#x5316;

    Set<character> ans = new HashSet<>();
    //
    Map<character , integer> indexMap = new HashMap<>();
    int i = 0;
//    show();
    for (char aa :VN){
      indexMap.put(new Character(aa) , i++);
    }
//    System.out.println(indexMap);
    Set<character> VNSet = arrToSet(VN);
    Set<character> VTSet = arrToSet(VT);
    char[] des = a.des.toCharArray();
//    System.out.println(a.toString());
    if (des[0] == '#'){
      ans.add(new Character('#'));
      return ans;
    }
    for (char aa : des){
      if(VTSet.contains(aa)){
        ans.add(new Character(aa));
        return ans;
      }

      if (isIntroductionEmpty[ indexMap.get(aa) ] ){
        ans.addAll(firstSet.get(new Character(aa)));
        ans.remove(new Character('#'));
      }else {
        ans.addAll(firstSet.get(new Character(aa)));
        ans.remove(new Character('#'));
        return ans;

      }

    }

    ans.add(new Character('#'));

    return ans ;
  }

  Set<character> getFirstSet(String a){
    return getFirstSet(new pUnit("2",a));
  }

  Map<character , set<character>> getFollowSet(){

    if (followSet !=null){
      return followSet;
    }
    if (firstSet == null){
      getFirstSet();
    }
    Map<character , set<character>> ans = new HashMap<>();
    // &#x7531;&#x4E8E;&#x8981;&#x7EDF;&#x8BA1; &#x6BCF;&#x4E2A;  follow &#x90FD;&#x4E0D;&#x5728;&#x589E;&#x5927;&#x65F6;  &#x7ED3;&#x675F;   &#x6240;&#x4EE5;   &#x8FD9;&#x91CC;&#x7EDF;&#x8BA1;&#x4E00;&#x4E2A;&#x603B;&#x6570;
    int count = 0;// &#x6240;&#x6709;follow &#x4E3A;&#x7A7A;
    int i,j;
    int l = VN.length;
    // &#x521D;&#x59CB;&#x5316;
    for( char a : VN){
      ans.put(new Character(a) , new HashSet<>());
    }

    // &#x8BBE;A&#x4E3A;&#x6587;&#x6CD5;&#x5F00;&#x59CB;&#x7B26;&#x53F7;&#xFF0C;&#x628A;#&#x52A0;&#x5165;FOLLOW(A)&#x4E2D;&#xFF0C;&#xFF08;#&#x4E3A;&#x53E5;&#x5B50;&#x62EC;&#x53F7;&#xFF09;
    ans.get(new Character(S)).add(new Character('#'));
    int update = 1;

    Set<character> VNSet = arrToSet(VN);
    Set<character> VTSet = arrToSet(VT);

    while (count != update){
      count = update;
      // &#x904D;&#x5386; &#x6240;&#x6709;&#x4EA7;&#x751F;&#x5F0F;
      i=0;
      for (ArrayList<punit> now : P){
        for (pUnit x : now){
          String des = x.des;
          char[] lis = des.toCharArray();
          char source = x.source.charAt(0);

          // &#x7B2C;&#x4E8C;&#x6B65;
          /*
          2&#xFF09;&#x82E5;B&#xF0AE;&#x3B1;A&#x3B2;&#x662F;&#x4E00;&#x4E2A;&#x4EA7;&#x751F;&#x5F0F;&#xFF0C;&#x5219;&#x628A;FIRST(&#x3B2;)&#x7684;&#x975E;&#x7A7A;&#x5143;&#x7D20;&#x52A0;&#x5165;FOLLOW(A)&#x4E2D;&#x3002;
          &#x5982;&#x679C;&#x3B2;   &#x3B5;&#xFF0C;&#x5219;&#x628A;FOLLOW(B)&#x4E5F;&#x52A0;&#x5165;FOLLOW(A)&#xFF1A;
          &#x56E0;&#x4E3A;&#x5F53;&#x6709;&#x5F62;&#x5982;D&#xF0AE;&#x3B1;1B&#x3B2;1   B&#xF0AE;&#x3B1;A&#x3B2;&#x7684;&#x4EA7;&#x751F;&#x5F0F;&#x65F6;&#xFF0C;A&#x3001;B&#x3001;D&#x2208;VN, &#x3B1;1,&#x3B2;1,&#x3B1;,&#x3B2;&#x2208;V*,&#x5728;&#x63A8;&#x5BFC;&#x8FC7;&#x7A0B;&#x4E2D;&#x53EF;&#x80FD;&#x51FA;&#x73B0;&#x53E5;&#x578B;&#x5E8F;&#x5217;&#x5982;
          S     &#x2026;&#x3B1;1B&#x3B2;1&#x2026;=>&#x2026;&#x3B1;1&#x3B1;A&#x3B2;&#x3B2;1 &#x2026;=> &#x2026;&#x3B1;1&#x3B1;A&#x3B2;1,
          &#x6545;FIRST(&#x3B2;1)&#x2208;FOLLOW(B)&#x548C;FIRST(&#x3B2;1) &#x2208; FOLLOW(A),&#x6240;&#x4EE5;FOLLOW(B)&#xF0CD;FOLLOW(A)
           */
          // &#x8FC7;&#x6EE4;&#x6389; &#x53F3;&#x4FA7;&#x4E3A;&#x7A7A;&#x7684; &#x548C; &#x5168;&#x4E3A;&#x7EC8;&#x7ED3;&#x7B26;&#x7684;&#x4EA7;&#x751F;&#x5F0F;
          if (des.equals("#" )|| VTSet.containsAll(arrToSet(lis)) ){
            continue;
          }

          // &#x542B;&#x6709; &#x975E;&#x7EC8;&#x7ED3;&#x7B26;   &#x68C0;&#x6D4B;
          for(i=0 ;i<lis.length ; i++){ if (vnset.contains(lis[i])){ 是非终结符 (i="=" lis.length-1){ 最后一个 ans.get(lis[i]).addall( ans.get(new character(source)) ); continue; } string sub="des.substring(i+1);" set<character> fir = getFirstSet(sub);
              //
              ans.get(lis[i]).addAll(fir);
              if (fir.contains(new Character('#'))){
                ans.get(lis[i]).addAll( ans.get(new Character(source)) );
              }else {

              }
            }
          }
        }
      }

      update = 0;
      for(char aaa: VN){
        update  = update+ ans.get(new Character(aaa)).size();
      }
    }

    this.followSet = ans;
    return ans;
  }

  Map<string , set<character>> getSelectSet() {

    if (selectSet != null){
      return selectSet;
    }

    if (firstSet == null){
      getFirstSet();
    }
    if (followSet == null){
      getFollowSet();
    }

    Map<string, set<character>> ans = new HashMap<>();

    for (ArrayList<punit> a : P) {
      for (pUnit b : a) {

//         &#x8FD9;&#x91CC;&#x5C55;&#x793A;&#x5404;&#x4EA7;&#x751F;&#x5F0F;&#x7684;&#x53F3;&#x90E8;&#x7B26;&#x53F7;&#x4E32;&#x7684;first&#x96C6;&#x5408;
        ans.put(b.toString(), getSelectSet(b));
//        System.out.println(b.toString());

      }
    }

    selectSet = ans;
    return ans;
  }

  Set<character> getSelectSet( pUnit a ){
//    if (selectSet == null){
//     getSelectSet();
//    }

//    System.out.println(a.toString());
    if (a.des == "#"){
      return followSet.get(new Character(a.source.charAt(0)));
    }

    Set<character> now = getFirstSet(a);
    if (now.contains(new Character('#'))){
      now.remove(new Character('#'));
      if (this.followSet ==  null){
        getFollowSet();
      }
      Set<character> as = followSet.get(new Character(a.source.charAt(0)));
      now.addAll(as);
      return now;
    }else {
      return now;
    }
  }

}

class pUnit {
  String source;
  String des;

  public pUnit() {
  }

  @Override
  public String toString() {
    return source + "->" + des;
  }

  public pUnit(String source, String des) {
    this.source = source;
    this.des = des.replaceAll("\n","");
  }

  public pUnit(char source, String des) {
    this.source = String.valueOf(source);
    this.des = des;
  }

  public pUnit(pUnit a) {
    this.des = a.des;
    this.source = a.source;
  }

  boolean desContainEndChar(char[] VT){
    for (char a : VT){
      if (des.indexOf(a) !=-1){
        return true;
      }
    }

    return false;
  }

  boolean desIsEmpty(){
    if (des.equals("#") || des.equals("")){
      return true;
    }

    return false;
  }

}

</character></character></character></punit></string,></string></lis.length></punit></character></character></character></character></character></character></character></character></character></character></character></character></character></character></=i<=n),则first(y1)-{ε},></character></punit></character></character></character></character></character></character></character></character></l></punit></punit></punit></character></character></punit></len2></punit></len2></character></character></punit></character></character></character></punit></character></len2></character></character></character></character></string></character></character></punit></='z')></='z')></vn.size()></character></character></character></character></character>

这里没有添加main 函数ou 直接新建一个LL1analysis类就行了

个人作品, 如有错误,请指出; 如要转载,请注明出处。 三克油。。

Original: https://www.cnblogs.com/cndccm/p/16317625.html
Author: Mr小明同学
Title: 编译原理实验LL1分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711517/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球