编译方法实验报告(中间代码生成器)

时间:2024.4.20

编译方法实验报告

20##年10月


一、            实验目的

熟悉算术表达式的语法分析与中间代码生成原理。

二、            实验内容

(1)设计语法制导翻译生成表达式的四元式的算法;

(2)编写代码并上机调试运行通过。

输入——算术表达式;

输出——语法分析结果;

相应的四元式序列。

(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文法,使用扩展的语法分析器实现语法制导翻译。

三、            实验原理及基本步骤

●算术表达式文法:

G(E):      E à E ω0 T | T

                T à T ω1 F | F

F à i | (E)

●文法变换:

G’(E)       E à T {ω0 T}

                   T à F {ω1 F}

F à i | (E)

●属性翻译文法:

E à T {ω0 “push(SYN, w)” T “QUAT”}

              T à F {ω1 “push(SYN, w)” F “QUAT”}

F à i “push(SEM, entry(w))” | (E)         

其中:

push(SYN, w) — 当前单词w入算符栈SYN;

push(SEM, entry(w)) — 当前w在符号表中的入口值压入语义栈SEM;

 QUAT — 生成四元式函数

         i.T = newtemp;

         ii.QT[j] =( SYN[k], SEM[s-1], SEM[s], T);  j++;  

iii.pop( SYN, _ );  pop( SEM, _ );  pop( SEM, _ );

push( SEM, T );

●递归下降子程序:

数据结构:SYN —算符栈;

SEM —语义栈;

四、            数据结构设计

使用递归的结构进行四元式的设计,同时,运用堆栈结构将四元式的输出序列打印出来

while ( exp[i]=='+' || exp[i]=='-'){

             syn[++i_syn]=exp[i];                  //push(SYN,w)

             i++;                                //read(w)

             T();

             quat();}

while ( exp[i]=='*' || exp[i]=='/'){

             syn[++i_syn]=exp[i];                  //push(SYN,w)

             i++;                                //read(w)

             F();

             quat();}

void quat(){

      strcpy(qt[j],"(, , , )");                    //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);

      qt[j][1]=syn[i_syn];

      qt[j][3]=sem[i_sem-1];

      qt[j][5]=sem[i_sem];

      qt[j][7]=temp;

      j++;

      i_syn--;                           //pop(SYN);

      i_sem--;                           //pop(SEM);

      i_sem--;                           //pop(SEM);

      sem[++i_sem]=temp;                //push(SEM,temp);

   temp++;}

五、            关键代码分析(带注释)及运行结果

#include <iostream>

#include "string.h"

#include "stdio.h"

using namespace std;

char syn[10];                                   //文法符号栈

int i_syn;

char sem[10];                                   //运算对象栈

int i_sem;

char exp[50];                                   //算术表达式区

int i;

char qt[30][15];                                 //四元式区

int j=0;

char temp='q';                               //临时变量,取值为r--z

int E();

int T();

int F();

void quat();                                    //生成四元式函数

int main(int argc, char* argv[]){

       printf("please input your expression:");

    scanf("%s",exp);                             //输入四元式

       i=0;                                         //read(w)

    E();

       if (exp[i]=='\0')

              for (i=0;i<j;i++)                        //输出四元式序列

                     printf("%s\n",qt[i]);

       else

              printf("err");

       return 0;}

int E(){

       T();

       while ( exp[i]=='+' || exp[i]=='-'){

              syn[++i_syn]=exp[i];                  //push(SYN,w)

              i++;                                //read(w)

              T();

              quat();}

       return 1;}

int T(){

       F();

       while ( exp[i]=='*' || exp[i]=='/'){

              syn[++i_syn]=exp[i];                  //push(SYN,w)

              i++;                                //read(w)

              F();

              quat();}

       return 1;}

int F(){

       if ( exp[i]=='('){

              i++;                                   //read(w)

              E();

              if ( exp[i]!=')'){

                     printf("err");

                     return 0;}

       }else if ((exp[i]>='a' && exp[i]<='p')||(exp[i]>='0' && exp[i]<='9')){

              sem[++i_sem]=exp[i]; }                 //push(SEM,w)

       else{

              printf("err");

              return 0;}

       i++;                                     //read(w)

       return 1;}

void quat(){

       strcpy(qt[j],"( , , , )");                    //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);

       qt[j][1]=syn[i_syn];

       qt[j][3]=sem[i_sem-1];

       qt[j][5]=sem[i_sem];

       qt[j][7]=temp;

       j++;

       i_syn--;                               //pop(SYN);

       i_sem--;                               //pop(SEM);

       i_sem--;                               //pop(SEM);

       sem[++i_sem]=temp;                     //push(SEM,temp);

    temp++;}

六、            总结与分析

我们知道,定义一种语言除了要求定义语法外,还要求定义语义,即对语言的各种语法单位赋予具体的意义。语义分析的任务是首先对每种语法单位进行静态的语义审查,然后分析其含义,并用另一种语言形式,即比源语言更加接近于目标语言的一种中间代码来进行描述这种语言。因此,中间代码就显得十分重要,它关系着整个程序语言的正确编译与否,同时也是进行下一步编译的重要先决条件。

七、            实验思考题

(1)自顶向下法(推导法)

从开始符号出发,采用推导运算,试图自顶向下构造语法树。

     自底向上法(归约法)

     从给定的符号串出发,采用归约运算,试图自底向上构造语法树。

(2)递归下降子程序法:递归子程序法属于自顶向下语法分析方法。故又名递归下降法。要求文法是LL(1)文法。

     LL(1)分析法:LL(1)分析法是指从左到右扫描(第一个 L) 、最左推导(第二个 L)和只查看一个当前符号(括号中的 1)之意;LL(1)分析法又称预测分析法,属于自顶向下确定性语法分析方法。要求文法是LL(1)文法。

(3)相同点:都要求文法是LL(1)文法;都是自顶向下的分析方法;都通过分析下个字符来判断该进入哪个状态或者调用哪个函数。

     不同点:LL(1)分析法先建立起预测分析表,通过对分析栈的不断操作(出栈,入栈)来进行;递归下降子程序法是通过函数间的函数调用来实现不同状态间的转换,并简化了代码。

(4)语法制导翻译是在语法分析过程中,随着分析(推导或归约)的逐步进展,每识别出一个语法结构,根据文法的每个规则所对应的语义子程序进行翻译的方法;核心技术是构造属性翻译文法。

(5)假定:SEM(m)-- 语义栈(属性传递、赋值场所);

QT[q] – 四元式区;

G``(E):E -> T | E+T{GEQ(+)} | E-T{GEQ(-)}   T -> F | T*F{GEQ(*)} | T/F{GEQ(/)}

F -> i{PUSH(i)} | ( E )  

其中:

⑴ PUSH(i)– 压栈函数(把当前 i 压入语义栈);

⑵ GEQ(w) – 表达式四元式生成函数:

生成一个四元式送QT[q]过程:

① t := NEWT; { 申请临时变量函数;}

② SEND(w,SEM[m-1],SEM[m],t)

③ POP;POP;PUSH(t)


第二篇:《编译方法》实验指导书


目录

实验一 词法分析器设计... 1

【实验目的】... 1

【实验内容】... 1

【流程图】... 1

【源代码】... 2

【程序部分截图】... 18

实验二 LL(1)语法分析程序设计... 20

【实验目的】... 20

【实验内容】... 20

【实验步骤和要求】... 20

【流程图】... 20

【源代码】... 21

【程序截图】... 32


实验一 词法分析器设计

【实验目的】

1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。

2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。

3.通过完成词法分析程序,了解词法分析的过程。

【实验内容】

用JAVA语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。

【流程图】

 



【源代码】


package accidence_analyse;

import java.io.*;

import java.util.*;

import buffer.*;

public class AccidenceAnalyser {

  private java.io.File SourceFile;

  private java.io.File ReserveFile;

  private java.io.File ClassFile;

  private java.io.File OutputFile;

  public Pretreatment pretreatment;

  public KeyWordTable keyWordTable;

  public ClassIdentity classIdentity;

  public Scaner scaner;

  public ConcreteScanBufferFactory csbFactory;

  /**

   * 2) 词法分析器主程序

   */

  public AccidenceAnalyser() {

    System.out.println("[INFOR]已经建立词法分析器!");

  }

  public void initAA() {

    //创建缓冲工厂

   this.csbFactory=newConcreteScanBufferFactory();

    //创建字符串扫描对象

    scaner = new Scaner(this);

    //创建pre处理对象

   pretreatment=newPretreatment(SourceFile, this);

    //创建关键字表对象

    keyWordTable= new KeyWordTable(ReserveFile);

    //创建对象种别码表对象

    classIdentity = new ClassIdentity(ClassFile);

    System.out.println("[INFOR]已经初始化词法分析器!"); }

  public void setFilesPath(String reserveFileName, String ClassFileName,String sourceFileName, String outputFileName) {

    //创建文件对象

    SourceFile = new java.io.File(sourceFileName);

    //创建文件对象

    ReserveFile = new java.io.File(reserveFileName);

    //创建文件对象

    ClassFile = new java.io.File(ClassFileName);

    //创建文件对象

    OutputFile = new java.io.File(outputFileName);

    //如果文件已经存在,先删除,然后建立新文件

if (OutputFile.exists()) {OutputFile.delete();}

try {OutputFile.createNewFile();}

   catch(Exceptione){e.printStackTrace(System.err);}

    try {

      //创建文件随机读取对象java.io.RandomAccessFile ROutputFile = new java.io.RandomAccessFile(this.

          OutputFile, "rw");

 //提示信息

ROutputFile.write("///////////////////////////////////////\n".getBytes());

     ROutputFile.write( ("//JAccidenceAnalyser version " + getVersion() +" design by yellowicq//\n").getBytes());

      ROutputFile.write("//java词法分析器//////////////\n".getBytes());

 ROutputFile.write("//使用java语言开发///\n".getBytes());

ROutputFile.write("\n".getBytes());

      ROutputFile.write("词法分析结果如下:\n".getBytes());

      //关闭文件流

      ROutputFile.close();

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

  }

  public void startAA() {

    //从预处理开始词法分析

    this.pretreatment.startPretreatment();

  }

  public void outputAccidence(String outputString) {

    //把分析出来的单词写入文件

    outputString="\n[第" + this.pretreatment.fileRow + "行]\n" + outputString;

    try {

      //创建文件随机读取对象

      java.io.RandomAccessFile ROutputFile = new java.io.RandomAccessFile(this.OutputFile, "rw");

      //移动指针到文件末尾

      ROutputFile.seek(ROutputFile.length());

      //Start appending!

      ROutputFile.write(outputString.getBytes());

      //关闭文件流

      ROutputFile.close();

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

    //将分析的单词结果输出到终端

    System.out.print(outputString);

  }

  public void controlThread() {

    //控制扫描器启动扫描

    scaner.controlThread();

  }

  //获得版本号

  public String getVersion() {

    return "1.0";

  }

}

package accidence_analyse;

import java.util.*;

import java.io.*;

public class ClassIdentity {

  private Hashtable ClassHash;

  private File ClassFile;

  private FileReader classFileReader; //读文件对象

  private int TMP_BUFFER_SIZE = 30;

  /**

   * 6) 类型种别码程序

   */

  public ClassIdentity(java.io.File ClassFile) {

    System.out.println("[INFOR]类型种别码表已创建!");

    this.ClassFile = ClassFile;

  }

  //查找类型种别码

  public int findKey(String classWord) {

    int KEY;

    for (Enumeration e = this.ClassHash.keys(); e.hasMoreElements(); ) {

      KEY=Integer.parseInt((String)e.nextElement());

if( ( (String)this.ClassHash.get(Integer.toString(KEY))).equalsIgnoreCase(classWord)) {return KEY;}

    }

    return -1;

  }

  public void initClassIdentityTable() {

    ClassHash = new Hashtable(); //创建hash表

    int intLength;

    char[] chrBuffer = new char[TMP_BUFFER_SIZE];

    String classWord;

    int classCounter = 0;

    try {

      if (ClassFile.exists()) { //文件存在

        //创建读文件对象

   classFileReader=newjava.io.FileReader(ClassFile);

        //读文件内容到hash表

 while((intLength=classFileReader.read(chrBuffer)) != -1) {

          classCounter++;

          //填写hash表

          classWord = String.valueOf(chrBuffer).trim();

          System.out.println("[INFOR]读取类型种别码: [KEY: " + classCounter + "][VALUE: " + classWord + "]");

    this.ClassHash.put(Integer.toString(classCounter), classWord);

        }

        //关闭读文件对象

        classFileReader.close();

      }

      else { //文件不存在

        System.err.println("[ERROR]类型种别码文件不存在!");

      }

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

  }

}

package accidence_analyse;

import java.util.*;

import java.io.*;

public class KeyWordTable {

  private Hashtable KWHash;

  private File ReserveFile;

  private FileReader resFileReader; //读文件对象

  private int TMP_BUFFER_SIZE = 30;

  /**

   * 5) 表留字表程序

   */

  public KeyWordTable(java.io.File ReserveFile) {

    System.out.println("[INFOR]关键字表已创建!");

    this.ReserveFile = ReserveFile;

  }

  public boolean isKeyWord(String inw) {

    String resWord;

    //查找hash表

    for (Enumeration e = this.KWHash.elements(); e.hasMoreElements(); ) {

      resWord = (String) e.nextElement();

      if (resWord.equalsIgnoreCase(inw)) {

        return true;

      }

    }

    return false;

  }

  public void initKeyWordTable() {

    KWHash = new Hashtable(); //创建hash表

    int intLength;

    char[] chrBuffer = new char[TMP_BUFFER_SIZE];

    String resWord;

    int resCounter = 0;

    try {

      if (ReserveFile.exists()) { //文件存在

        //创建读文件对象

        resFileReader = new java.io.FileReader(ReserveFile);

        //读文件内容到hash表

while((intLength = resFileReader.read(chrBuffer))!= -1) {          resCounter++;

//填写hash表

          resWord = String.valueOf(chrBuffer).trim();

          System.out.println("[INFOR]读取关键字: [INDEX: " + resCounter +"][VALUE: " + resWord + "]");

this.KWHash.put(Integer.toString(resCounter), resWord);}

        //关闭读文件对象

        resFileReader.close();

      }

      else { //文件不存在

        System.err.println("[ERROR]保留字文件不存在!");

      }

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

  }

}

package accidence_analyse;

import javax.xml.parsers.*;

import org.w3c.dom.*;

public class main {

  /**

   * 1) 词法分析器引导文件

   */

  public static void main(String[] args) {

//读取配置文件,得到系统属性

    String cfgString[] = new String[4];

    try {

      cfgString = main.loadAACfg("d:\\aaCfg.xml");

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

//设置待读文件名

    //保留字表文件

    String reserveFileName = cfgString[0];

    //类型种别码表文件

    String classFileName = cfgString[1];

    //需要分析的源文件

    String sourceFileName = cfgString[2];

    //输出文件

    String outputFileName = cfgString[3];

    //创建词法分析器

    AccidenceAnalyser aa=new AccidenceAnalyser();

aa.setFilesPath(reserveFileName, classFileName, sourceFileName,outputFileName);

//建立所需要的文件对象

    //初始化词法分析器

    aa.initAA();

    //初始化关键字表

    aa.keyWordTable.initKeyWordTable();

    //初始化类型种别码表

    aa.classIdentity.initClassIdentityTable();

    //开始进行词法分析

    aa.startAA();

    //分析完毕

  }

  //读取配置文件

  private static String[] loadAACfg(String name) throws Exception {

    String cfgString[] = new String[4];

    /*解析xml配置文件*/

    try {

      /*创建文档工厂*/

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

      /*创建文档解析器*/

      DocumentBuilder builder = factory.newDocumentBuilder();

      /*解析配置文件*/

      Document doc = builder.parse(name);

      /*规范化文档*/

      doc.normalize();

      /*查找接点表*/

      NodeList nlists = doc.getElementsByTagName("FilePath");

      for (int i = 0; i < nlists.getLength(); i++) {

        Element item = (Element) nlists.item(i);

        //取得需要的配置属性

        cfgString[0] = item.getElementsByTagName("ReserveFileName").item(0).getFirstChild().getNodeValue().trim();

cfgString[1] = item.getElementsByTagName("ClassFileName").item(0).

            getFirstChild().getNodeValue().trim();

        cfgString[2] = item.getElementsByTagName("SourceFileName").item(0).

            getFirstChild().getNodeValue().trim();

        cfgString[3] = item.getElementsByTagName("OutputFileName").item(0).

            getFirstChild().getNodeValue().trim();

      }

    }

    catch (Exception e) {

      e.printStackTrace();

      throw new Exception("[ERROR]加载配置文件 " + name + " 错误!");

    }

    //返回属性数组

    return cfgString;

  }

}

package accidence_analyse;

import java.io.*;

import buffer.*;

public class Pretreatment {

  private String tmpString;

  private String outputString;

  private int BUFFER_SIZE = 100;

  private AccidenceAnalyser aa;

  public InputBuffer inputBuffer; //输入缓冲区--共享

  private java.io.File SourceFile; //文件对象

  private java.io.RandomAccessFile randomAFile; //随机文件对象

  public static int fileRow = 0;

  /**

   * 3) 预处理子程序

   */

  public Pretreatment(File SourceFile, AccidenceAnalyser aa) {

    try {

      this.SourceFile = SourceFile;

      this.randomAFile = new java.io.RandomAccessFile(this.SourceFile, "r");

    }

    catch (FileNotFoundException e) {

      e.printStackTrace(System.err);

    }

    this.aa = aa;

    inputBuffer = aa.csbFactory.createInputBuffer(BUFFER_SIZE);

    System.out.println("[INFOR]预处理器已经创建!");

  }

  public void putSourceToINBuffer(String tmpString) {

    this.inputBuffer.Data = tmpString.toCharArray();

  }

  public void putFinToSCBuffer(String filtratedString) {

    aa.scaner.scanBuffer.Data = filtratedString.toCharArray();

  }

  public void controlThread() {

    int intLength;

    int resCounter = 0;

    String tmpString;

    String filtratedString;

    System.out.println("[INFOR]开始单词分析////////////////////////////////////////");

    try {

      if (SourceFile.exists()) { //文件存在

        //读文件内容到缓冲区

        while ( (tmpString = this.randomAFile.readLine()) != null) {

          ++fileRow;

          //分割符

          System.out.println("...................begin row " + this.fileRow +

                             ".......................");

          //开始这一行分析

          System.out.println("[INFOR]正在处理行: " + String.valueOf(fileRow));

          //放入输入缓冲区

          this.putSourceToINBuffer(tmpString);

          //处理字符串

          filtratedString = this.filtrateSource(this.inputBuffer.Data);

          System.out.println("[INFOR]已过滤句子: " + filtratedString);

          //放入扫描缓冲区

          this.putFinToSCBuffer(filtratedString);

          aa.controlThread();

        }

        System.out.println(

            "[INFOR]分析完毕////////////////////////////////////////////");

      }

      else { //文件不存在

        System.err.println("[ERROR]源文件不存在!");

      }

    }

    catch (Exception e) {

      e.printStackTrace(System.err);

    }

  }

  public String filtrateSource(char[] Data) {

    String filtratedString = String.valueOf(Data).trim();

    return filtratedString;

  }

  public void startPretreatment() {

    this.controlThread();

  }

}

package accidence_analyse;

import buffer.*;

publicclass Scaner {

  public ScanBuffer scanBuffer; //扫描缓冲区--共享

  private String finalAccidence;

  private AccidenceAnalyser aa;

  privateint BUFFER_SIZE = 100;

  private String toDelString;

  privateint senLength = 0;

  privatechar[] sentenceChar = newchar[1000];

  private String TOKEN;

  privatechar CHAR;

  privateint index = 0;

  private String IDENTITY = "identity";

  private String DIGIT = "digit";

  private String WORD_ERROR_INF = "在此行发现不能识别的单词,此行分析终止!";

  privateboolean ASTATE = true;

  /**

   * 4) 扫描子程序

   */

  public Scaner(AccidenceAnalyser aa) {

    this.aa = aa;

    initBuffer();

    this.finalAccidence = "";

    System.out.println("[INFOR]扫描处理器已经创建!");

  }

  public String readFromBuffer(char[] Data) {

    String toDelString = String.valueOf(Data);

    return toDelString;

  }

  public String scan(String toDelString) {

    sentenceChar = toDelString.toCharArray();

    this.senLength = sentenceChar.length;

    inti = 0;

    //分析单词

    while (this.index <= this.senLength) {

      //state0:

      this.TOKEN = "";

      this.CHAR = GETBC(sentenceChar);

      if (this.CHAR == ';') {

        break; //';'表示这一行结束

      }

      //进入状态判断

      switch (this.CHAR) {

        //judge letter

case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':

case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':

case 'z':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':

case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':

          //do

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          //state1

          CHAR = this.GETCHAR(sentenceChar);

          while (this.ISLETTER(CHAR) || this.ISDIGIT(CHAR)) {

            this.TOKEN = this.CONTACT(this.TOKEN, CHAR);

            CHAR = this.GETCHAR(sentenceChar);

          }

          this.RETRACT();

          //state2

          if (aa.keyWordTable.isKeyWord(TOKEN)) {

            this.finalAccidence = this.finalAccidence + "[保留字] " +

                this.returnAWord(TOKEN) + "\n";

          }

          else {

            this.finalAccidence = this.finalAccidence + "[标识符] " +

                this.returnAWord(TOKEN) + "[种别码] " +

                String.valueOf(aa.classIdentity.findKey(IDENTITY)) + "\n";

          }

          //clear up token

          this.TOKEN = "";

          break;

          //judge ditital

        case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':

          //do

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          //state3

          CHAR = this.GETCHAR(sentenceChar);

          while (this.ISDIGIT(CHAR)) {

            this.TOKEN = this.CONTACT(TOKEN, CHAR);

            CHAR = this.GETCHAR(sentenceChar);

          }

          this.RETRACT();

          //state4

          this.finalAccidence = this.finalAccidence + "[数字] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(DIGIT)) + "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '=':

          //state5

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[等号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '+':

          //state6

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[加号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '*':

          //state7

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          CHAR = this.GETCHAR(sentenceChar);

          //state8

          if (CHAR == '*') {

            this.TOKEN = this.CONTACT(TOKEN, CHAR);

            this.finalAccidence = this.finalAccidence + "[乘方] " +

                this.returnAWord(TOKEN) + "[种别码] " +

                String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

                "\n";

          }

          //state9

          else {

            this.finalAccidence = this.finalAccidence + "[乘号] " +

                this.returnAWord(TOKEN) + "[种别码] " +

                String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

                "\n";

          }

          //clear up token

          this.TOKEN = "";

          break;

        case ',':

          //state10

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[逗号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '(':

          //state11

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[左括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case ')':

          //state12

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[右括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '{':

          //state13

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[左大括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '}':

          //state14

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[右大括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '[':

          //state15

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[左中括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case ']':

          //state16

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[右中括号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        case '.':

          //state17

          this.TOKEN = this.CONTACT(TOKEN, CHAR);

          this.finalAccidence = this.finalAccidence + "[点号] " +

              this.returnAWord(TOKEN) + "[种别码] " +

              String.valueOf(aa.classIdentity.findKey(String.valueOf(CHAR))) +

              "\n";

          //clear up token

          this.TOKEN = "";

          break;

        default:

          //state18

          this.TOKEN = this.CONTACT(this.TOKEN, this.CHAR);

          //追加出错信息

          this.finalAccidence = this.finalAccidence + "[ERROR]" +

              this.WORD_ERROR_INF + "'" + this.TOKEN + "'" + "\n";

          this.ASTATE = false;

          //clear up token

          this.TOKEN = "";

          break;

      }

      if (this.ASTATE == false) {

        break;

      }

    }

    returnthis.finalAccidence;

  }

  publicvoid controlThread() {

    this.toDelString = this.readFromBuffer(this.scanBuffer.Data);

    this.aa.outputAccidence(this.scan(this.toDelString));

    //分割符

    System.out.println("...................end row " + aa.pretreatment.fileRow +

                       ".........................");

    //结束这一行分析

    //clear up the var

    this.index = 0;

    this.finalAccidence = "";

    this.ASTATE = true;

    this.toDelString = "";

    this.senLength = 0;

    this.TOKEN = "";

  }

  public String returnAWord(String TOKEN) {

    return TOKEN;

  }

  publicvoid initBuffer() {

    this.scanBuffer = aa.csbFactory.createScanBuffer(BUFFER_SIZE);

  }

//以下为字符的处理方法

  publicchar GETBC(char[] sentenceChar) {

    try {

      while ( (sentenceChar[this.index]) == ' ') {

        this.index++;

      }

      this.index++;

    }

    catch (java.lang.ArrayIndexOutOfBoundsException e) {

      return ';'; //表示此行已经结束

    }

    return sentenceChar[index - 1];

  }

  publicchar GETCHAR(char[] sentenceChar) {

    next();

    return sentenceChar[this.index - 1];

  }

  publicvoid next() {

    this.index++;

  }

  publicboolean ISLETTER(char letter) {

    return java.lang.Character.isLetter(letter);

  }

  publicboolean ISDIGIT(char letter) {

    return java.lang.Character.isDigit(letter);

  }

  public String CONTACT(String TOKEN, char CHAR) {

    String tmpS = TOKEN + String.valueOf(CHAR);

    TOKEN = tmpS;

    return TOKEN;

  }

  publicboolean ISRESERVE(String TOKEN) {

    return aa.keyWordTable.isKeyWord(TOKEN);

  }

  publicvoid RETRACT() {

    this.index--;

  }

}

package buffer;

//abstract buffer interface

publicinterface Buffer {

}

package buffer;

publicinterface BufferFactory {

  /**

   * 7) 抽象扫描缓冲区工厂

   */

  public ScanBuffer createScanBuffer(int size);

  public InputBuffer createInputBuffer(int size);

}

package buffer;

publicclass ConcreteScanBufferFactory

    implements BufferFactory {

  /**

   * 8) 缓冲区工厂

   */

  public ConcreteScanBufferFactory() {

    System.out.println("[INFOR]缓冲区工厂已经建立!");

  }

  public ScanBuffer createScanBuffer(int size) {

    System.out.println("[INFOR]创建扫描缓冲区!");

    returnnew ScanBuffer(size);

  }

  publicInputBuffer createInputBuffer(int size) {

    System.out.println("[INFOR]创建输入缓冲区!");

    returnnew InputBuffer(size);

  }

}

package buffer;

importjava.io.*;

publicclass InputBuffer

    implements Buffer {

  publicchar[] Data;

  /**

   * 10) 输入缓冲区对象

   */

  public InputBuffer(int size) {

    this.Data = newchar[size];

  }

}


package buffer;

publicclass ScanBuffer

    implements Buffer {

  publicchar[] Data;

  /**

   * 11) 扫描缓冲区对象

   */

  public ScanBuffer(int size) {

    this.Data = newchar[size];

  }

}

【程序部分截图】

实验二 LL(1)语法分析程序设计

【实验目的】

1.熟悉判断LL(1)文法的方法及对某一输入串的分析过程。

2.学会构造表达式文法的预测分析表。

【实验内容】

编写一个语法分析程序,对于给定的输入串,能够判断识别该串是否为给定文法的句型。

【实验步骤和要求】

1. 从键盘读入输入串,并判断正误;

2. 若无误,由程序自动构造FIRST、FOLLOW集以及SELECT集合,判断是否为LL(1)文法;

3. 若符合LL(1)文法,由程序自动构造LL(1)分析表;

4. 由算法判断输入符号串是否为该文法的句型。(可参考教材96页的例题1)

【流程图】

 

【源代码】
#include "stdio.h"
#include "stdlib.h"

#define MaxRuleNum 8
#define MaxVnNum 5
#define MaxVtNum 5
#define MaxStackDepth 20
#define MaxPLength 20
#define MaxStLength 50
struct pRNode /*产生式右部结构*/
{
 int rCursor; /*右部序号*/
 struct pRNode *next;
};

struct pNode /*产生式结点结构*/
{
 int lCursor; /*左部符号序号*/
 int rLength; /*右部长度*/
 /*注当rLength = 1 时,rCursor = -1为空产生式*/
 struct pRNode *rHead; /*右部结点头指针*/
};

char Vn[MaxVnNum + 1]; /*非终结符集*/
int vnNum;
char Vt[MaxVtNum + 1]; /*终结符集*/
int vtNum;
struct pNode P[MaxRuleNum]; /*产生式*/
int PNum; /*产生式实际个数*/
char buffer[MaxPLength + 1];
char ch; /*符号或string ch;*/
char st[MaxStLength]; /*要分析的符号串*/


struct collectNode /*集合元素结点结构*/
{
 int nVt; /*在终结符集中的下标*/
 struct collectNode *next;
};

struct collectNode* first[MaxVnNum + 1]; /*first集*/
struct collectNode* follow[MaxVnNum + 1]; /*follow集*/

int analyseTable[MaxVnNum + 1][MaxVtNum + 1 + 1];
/*预测分析表存放为产生式的编号,+1用于存放结束符,多+1用于存放#(-1)*/

int analyseStack[MaxStackDepth + 1]; /*分析栈*/
int topAnalyse; /*分析栈顶*/
/*int reverseStack[MaxStackDepth + 1]; /*颠倒顺序栈*/
/*int topReverse; /*倒叙栈顶*/


void Init();/*初始化*/
int IndexCh(char ch);
/*返回Vn在Vn表中的位置+100、Vt在Vt表中的位置,-1表示未找到*/
void InputVt(); /*输入终结符*/
void InputVn();/*输入非终结符*/
void ShowChArray(char* collect, int num);/*输出Vn或Vt的内容*/
void InputP();/*产生式输入*/
bool CheckP(char * st);/*判断产生式正确性*/
void First(int U);/*计算first集,U->xx...*/
void AddFirst(int U, int nCh); /*加入first集*/
bool HaveEmpty(int nVn); /*判断first集中是否有空(-1)*/
void Follow(int V);/*计算follow集*/
void AddFollow(int V, int nCh, int kind);/*加入follow集,
 kind = 0表加入follow集,kind = 1加入first集*/
void ShowCollect(struct collectNode **collect);/*输出first或follow集*/
void FirstFollow();/*计算first和follow*/
void CreateAT();/*构造预测分析表*/
void ShowAT();/*输出分析表*/
void Identify(char *st);/*主控程序,为操作方便*/
/*分析过程显示操作为本行变换所用,与教程的显示方式不同*/
void InitStack();/*初始化栈及符号串*/
void ShowStack();/*显示符号栈中内容*/
void Pop();/*栈顶出栈*/
void Push(int r);/*使用产生式入栈操作*/


#include "LL1.h"

void main(void)
{
 char todo,ch;
  Init();

 InputVn();
 InputVt();
 InputP();

 getchar();

 FirstFollow();
 printf("所得first集为:");
 ShowCollect(first);
 printf("所得follow集为:");
 ShowCollect(follow);

 CreateAT();
 ShowAT();

 todo = 'y';
 while('y' == todo)
 {
  printf("\n是否继续进行句型分析?(y / n):");
  todo = getchar();
  while('y' != todo && 'n' != todo)
  {
   printf("\n(y / n)? ");
   todo = getchar();
  }
  if('y' == todo)
  {
   int i;
   InitStack();
   printf("请输入符号串(以#结束) : ");
   ch = getchar();
   i = 0;
   while('#' != ch && i < MaxStLength)
   {
    if(' ' != ch && '\n' != ch)
    {
     st[i++] = ch;
    }
    ch = getchar();
   }
   if('#' == ch && i < MaxStLength)
   {
    st[i] = ch;
    Identify(st);
   }
   else
    printf("输入出错!\n");
  }
 }

 getchar();
}
void Init()
{
 int i,j;
 vnNum = 0;
 vtNum = 0;
 PNum = 0;
 for(i = 0; i <= MaxVnNum; i++)
  Vn[i] = '\0';
 for(i = 0; i <= MaxVtNum; i++)
  Vt[i] = '\0';
 for(i = 0; i < MaxRuleNum; i++)
 {
  P[i].lCursor = NULL;
  P[i].rHead = NULL;
  P[i].rLength = 0;
 }
 PNum = 0;
 for(i = 0; i <= MaxPLength; i++)
  buffer[i] = '\0';
 for(i = 0; i < MaxVnNum; i++)
 {
  first[i] = NULL;
  follow[i] = NULL;
 }
 for(i = 0; i <= MaxVnNum; i++)
 {
  for(j = 0; j <= MaxVnNum + 1; j++)
   analyseTable[i][j] = -1;
 }
}
/*返回Vn在Vn表中的位置+100、Vt在Vt表中的位置,-1表示未找到*/
int IndexCh(char ch) 
{
 int n;
 n = 0; /*is Vn?*/
 while(ch != Vn[n] && '\0' != Vn[n])
  n++;
 if('\0' != Vn[n])
  return 100 + n;
 n = 0; /*is Vt?*/
 while(ch != Vt[n] && '\0' != Vt[n])
  n++;
 if('\0' != Vt[n])
  return n;
 return -1;
}
/*输出Vn或Vt的内容*/
void ShowChArray(char* collect)
{
 int k = 0;
 while('\0' != collect[k])
 {
  printf(" %c ", collect[k++]);
 }
 printf("\n");
}
/*输入非终结符*/
void InputVn()
{
 int inErr = 1;
 int n,k;
 char ch;
 while(inErr)
 {
  printf("\n请输入所有的非终结符,注意:");
  printf("请将开始符放在第一位,并以#号结束:\n"); 
  ch = ' ';
  n = 0;
  /*初始化数组*/
  while(n < MaxVnNum)
  {
   Vn[n++] = '\0';
  }
  n = 0;
  while(('#' != ch) && (n < MaxVnNum))
  {
   if(' ' != ch && '\n' != ch && -1 == IndexCh(ch))
   {
    Vn[n++] = ch;
    vnNum++;
   }
   ch = getchar();
  }
  Vn[n] = '#'; /*以“#”标志结束用于判断长度是否合法*/
  k = n; /*k用于记录n以便改Vn[n]='\0'*/
  if('#' != ch)
  {
   if( '#' != (ch = getchar()))
   {
    while('#' != (ch = getchar()))
     ;
    printf("\n符号数目超过限制!\n");
    inErr = 1;
    continue;
   }
  }
  /*正确性确认,正确则,执行下下面,否则重新输入*/
  Vn[k] = '\0';
  ShowChArray(Vn);
  ch = ' ';
  while('y' != ch && 'n' != ch)
  {
   if('\n' != ch)
   {
    printf("输入正确确认?(y/n):");
   }
   scanf("%c", &ch);
  }
  if('n' == ch)
  {
   printf("录入错误重新输入!\n");
   inErr = 1;
  }
  else
  {
   inErr = 0;
  }
 }
}
/*输入终结符*/
void InputVt()
{
 int inErr = 1;
 int n,k;
 char ch;
 while(inErr)
 {
  printf("\n请输入所有的终结符,注意:");
  printf("以#号结束:\n"); 
  ch = ' ';
  n = 0;
  /*初始化数组*/
  while(n < MaxVtNum)
  {
   Vt[n++] = '\0';
  }
  n = 0;
  while(('#' != ch) && (n < MaxVtNum))
  {
   if(' '!= ch && '\n' != ch && -1 == IndexCh(ch))
   {
    Vt[n++] = ch;
    vtNum++;
   }
   ch = getchar();
  }
  Vt[n] = '#'; /*以“#”标志结束*/
  k = n; /*k用于记录n以便改Vt[n]='\0'*/
  if('#' != ch)
  {
   if( '#' != (ch = getchar()))
   {
    while('#' != (ch = getchar()))    

    printf("\n符号数目超过限制!\n");
    inErr = 1;
    continue;
   }
  }
  /*正确性确认,正确则,执行下下面,否则重新输入*/
  Vt[k] = '\0';
  ShowChArray(Vt);
  ch =' ';
  while('y' != ch && 'n' != ch)
  {
   if('\n' != ch)
   {
    printf("输入正确确认?(y/n):");
   }
   scanf("%c", &ch);
  }
  if('n' == ch)
  {
   printf("录入错误重新输入!\n");
   inErr = 1;
  }
  else
  {
   inErr = 0;
  }
 }
}
/*产生式输入*/
void InputP()
{
 char ch;
 int i = 0, n,num;
 printf("请输入文法产生式的个数:");
 scanf("%d", &num);
 PNum = num;
 getchar(); /*消除回车符*/
 printf("\n请输入文法的%d个产生式,并以回车分隔每个产生式:", num);
 printf("\n");
 while(i < num)
 {
  printf("第%d个:", i);
  /*初始化*/
  for(n =0; n < MaxPLength; n++)
   buffer[n] = '\0';
  /*输入产生式串*/
  ch = ' ';
  n = 0;
  while('\n' != (ch = getchar()) && n < MaxPLength)
  {
   if(' ' != ch)
    buffer[n++] = ch;    
  }
  buffer[n] = '\0';
/*  printf("%s", buffer);*/
  if(CheckP(buffer))
  {
   /*填写入产生式结构体*/
   pRNode *pt, *qt;
   P[i].lCursor = IndexCh(buffer[0]);
   pt = (pRNode*)malloc(sizeof(pRNode));
   pt->rCursor = IndexCh(buffer[3]);
   pt->next = NULL;
   P[i].rHead = pt;
   n = 4;
   while('\0' != buffer[n])
   {
    qt = (pRNode*)malloc(sizeof(pRNode));
    qt->rCursor = IndexCh(buffer[n]);
    qt->next = NULL;
    pt->next = qt;
    pt = qt;
    n++;
   }
   P[i].rLength = n - 3;
   i++;
   /*调试时使用*/
  }
  else
   printf("输入符号含非法在成分,请重新输入!\n");
 }
}
/*判断产生式正确性*/
bool CheckP(char * st)
{
 int n;
 if(100 > IndexCh(st[0]))
  return false;
 if('-' != st[1])
  return false;
 if('>' != st[2])
  return false;
 for(n = 3; '\0' != st[n]; n ++)
 {
  if(-1 == IndexCh(st[n]))
   return false;
 }
 return true;
}
/*====================first & follow======================*/
/*计算first集,U->xx...*/
void First(int U)
{
 int i,j;
 for(i = 0; i < PNum; i++)
 {
  if(P[i].lCursor == U)
  {
   struct pRNode* pt;
   pt = P[i].rHead;
   j = 0;
   while(j < P[i].rLength)
   {
    if(100 > pt->rCursor)
    {
     /*注:此处因编程出错,使空产生式时
     rlength同样是1,故此处同样可处理空产生式*/
     AddFirst(U, pt->rCursor);
     break;
    }
    else
    {
     if(NULL == first[pt->rCursor - 100])
     {
      First(pt->rCursor);
     }     
     AddFirst(U, pt->rCursor);
     if(!HaveEmpty(pt->rCursor))
     {
      break;
     }
     else
     {
      pt = pt->next;
     }
    }
    j++;
   }
   if(j >= P[i].rLength) /*当产生式右部都能推出空时*/
    AddFirst(U, -1);
  }
 }
}
/*加入first集*/
void AddFirst(int U, int nCh) /*当数值小于100时nCh为Vt*/
/*当处理非终结符时,AddFirst不添加空项(-1)*/
{
 struct collectNode *pt, *qt;
 int ch; /*用于处理Vn*/
 pt = NULL;
 qt = NULL;
 if(nCh < 100)
 {
  pt = first[U - 100];
  while(NULL != pt)
  {
   if(pt->nVt == nCh)
    break;
   else
   {
    qt = pt;
    pt = pt->next;
   }
  }
  if(NULL == pt)
  {
   pt = (struct collectNode *)malloc(sizeof(struct collectNode));
   pt->nVt = nCh;
   pt->next = NULL;
   if(NULL == first[U - 100])
   {
    first[U - 100] = pt;
   }
   else
   {
    qt->next = pt; /*qt指向first集的最后一个元素*/
   }
   pt = pt->next;
  }
 }
 else
 {
  pt = first[nCh - 100];
  while(NULL != pt)
  {
   ch = pt->nVt;
   if(-1 != ch)
   {
    AddFirst(U, ch);
   }
   pt = pt->next;
  }
 }
}
/*判断first集中是否有空(-1)*/
bool HaveEmpty(int nVn) 
{
 if(nVn < 100) /*为终结符时(含-1),在follow集中用到*/
  return false;
 struct collectNode *pt;
 pt = first[nVn - 100];
 while(NULL != pt)
 {
  if(-1 == pt->nVt)
   return true;
  pt = pt->next;
 }
 return false;
}
/*计算follow集,例:U->xVy,U->xV.(注:初始符必含#——"-1")*/
void Follow(int V)
{
 int i;
 struct pRNode *pt ;
 if(100 == V) /*当为初始符时*/
  AddFollow(V, -1, 0 );
 for(i = 0; i < PNum; i++)
 {
  pt = P[i].rHead;
  while(NULL != pt && pt->rCursor != V) /*注此不能处理:U->xVyVz的情况*/
   pt = pt->next;
  if(NULL != pt)
  {
   pt = pt->next; /*V右侧的符号*/
   if(NULL == pt) /*当V后为空时V->xV,将左符的follow集并入V的follow集中*/
   {
    if(NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V)
    {
     Follow(P[i].lCursor);
    }
    AddFollow(V, P[i].lCursor, 0);
   }
   else /*不为空时V->xVy,(注意:y->),调用AddFollow加入Vt或y的first集*/
   {
    while(NULL != pt && HaveEmpty(pt->rCursor))
    {

AddFollow(V, pt->rCursor, 1); /*y的前缀中有空时,加如first集*/
     pt = pt->next;
    }
    if(NULL == pt) /*当后面的字符可以推出空时*/
    {
     if(NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V)
     {
      Follow(P[i].lCursor);
     }
     AddFollow(V, P[i].lCursor, 0);
    }
    else /*发现不为空的字符时*/
    {
     AddFollow(V, pt->rCursor, 1);
    }
   }
  }
 } 
}

/*当数值小于100时nCh为Vt*/
/*#用-1表示,kind用于区分是并入符号的first集,还是follow集
kind = 0表加入follow集,kind = 1加入first集*/
void AddFollow(int V, int nCh, int kind)
{
 struct collectNode *pt, *qt;
 int ch; /*用于处理Vn*/
 pt = NULL;
 qt = NULL;
 if(nCh < 100) /*为终结符时*/
 {
  pt = follow[V - 100];
  while(NULL != pt)
  {
   if(pt->nVt == nCh)
    break;
   else
   {
    qt = pt;
    pt = pt->next;
   }
  }
  if(NULL == pt)
  {
   pt = (struct collectNode *)malloc(sizeof(struct collectNode));
   pt->nVt = nCh;
   pt->next = NULL;
   if(NULL == follow[V - 100])
   {
    follow[V - 100] = pt;
   }
   else
   {
    qt->next = pt; /*qt指向follow集的最后一个元素*/
   }
   pt = pt->next;
  }
 }
 else /*为非终结符时,要区分是加first还是follow*/
 {
  if(0 == kind)
  {
   pt = follow[nCh - 100];
   while(NULL != pt)
   {
    ch = pt->nVt;
    AddFollow(V, ch, 0);
    pt = pt->next;
   }
  }
  else
  {
   pt = first[nCh - 100];
   while(NULL != pt)
   {
    ch = pt->nVt;
    if(-1 != ch)
    {
     AddFollow(V, ch, 1);
    }
    pt = pt->next;
   }
  }
 }
}
/*输出first或follow集*/
void ShowCollect(struct collectNode **collect)
{
 int i;
 struct collectNode *pt;
 i = 0;
 while(NULL != collect[i])
 {
  pt = collect[i];
  printf("\n%c:\t", Vn[i]);
  while(NULL != pt)
  {
   if(-1 != pt->nVt)
   {
    printf(" %c", Vt[pt->nVt]);
   }
   else
    printf(" #");
   pt = pt->next;
  }
  i++;
 }
 printf("\n");
}
/*计算first和follow*/
void FirstFollow()
{
 int i;
 i = 0;
 while('\0' != Vn[i])
 {
  if(NULL == first[i])
   First(100 + i);
  i++;
 }
 i = 0;
 while('\0' != Vn[i])
 {
  if(NULL == follow[i])
   Follow(100 + i);
  i++;
 }
}
/*=================构造预测分析表,例:U::xyz=============*/
void CreateAT()
{
 int i;
 struct pRNode *pt;
 struct collectNode *ct;
 for(i = 0; i < PNum; i++)
 {
  pt = P[i].rHead;
  while(NULL != pt && HaveEmpty(pt->rCursor)) 
  {
   /*处理非终结符,当为终结符时,定含空为假跳出*/
   ct = first[pt->rCursor - 100];
   while(NULL != ct)
   {
    if(-1 != ct->nVt)
     analyseTable[P[i].lCursor - 100][ct->nVt] = i;
    ct = ct->next;
   }
   pt = pt->next;
  }
  if(NULL == pt)
  {
   /*NULL == pt,说明xyz->,用到follow中的符号*/
   ct = follow[P[i].lCursor - 100];
   while(NULL != ct)
   {
    if(-1 != ct->nVt)
     analyseTable[P[i].lCursor - 100][ct->nVt] = i;
    else /*当含有#号时*/
     analyseTable[P[i].lCursor - 100][vtNum] = i;
    ct = ct->next;
   }
  }
  else
  {
   if(100 <= pt->rCursor) /*不含空的非终结符*/
   {
    ct = first[pt->rCursor - 100];
    while(NULL != ct)
    {
     analyseTable[P[i].lCursor - 100][ct->nVt] = i;
     ct = ct->next;
    }
   }
   else /*终结符或者空*/
   {
    if(-1 == pt->rCursor) /*-1为空产生式时*/
    {
     ct = follow[P[i].lCursor - 100];
     while(NULL != ct)
     {
      if(-1 != ct->nVt)
       analyseTable[P[i].lCursor - 100][ct->nVt] = i;
      else /*当含有#号时*/
       analyseTable[P[i].lCursor - 100][vtNum] = i;
      ct = ct->next;
     }
    }
    else /*为终结符*/
    {
     analyseTable[P[i].lCursor - 100][pt->rCursor] = i;
    }
   }
  }
 }
}
/*输出分析表*/
void ShowAT()
{
 int i,j;

 printf("构造预测分析表如下:\n");
 printf("\t|\t");
 for(i = 0; i < vtNum; i++)
 {
  printf("%c\t", Vt[i]);
 }
 printf("#\t\n");

 printf("- - -\t|- - -\t");
 for(i = 0; i <= vtNum; i++)
  printf("- - -\t");
 printf("\n");

 for(i = 0; i < vnNum; i++)
 {
  printf("%c\t|\t", Vn[i]);
  for(j = 0; j <= vtNum; j++)
  {
   if(-1 != analyseTable[i][j])
    printf("R(%d)\t", analyseTable[i][j]);
   else
    printf("error\t");
  }
  printf("\n");
 }
}
/*=================主控程序=====================*/
void Identify(char *st)
{
 int current,step,r; /*r表使用的产生式的序号*/
 printf("\n%s的分析过程:\n", st);
 printf("步骤\t分析符号栈\t当前指示字符\t使用产生式序号\n");
 
 step = 0;
 current = 0; /*符号串指示器*/
 printf("%d\t",step);
 ShowStack();
 printf("\t\t%c\t\t- -\n", st[current]);

 while('#' != st[current])
 {
  if(100 > analyseStack[topAnalyse]) /*当为终结符时*/
  {
   if(analyseStack[topAnalyse] == IndexCh(st[current]))
   {
    /*匹配出栈,指示器后移*/
    Pop();
    current++;
    step++;
    printf("%d\t", step);
    ShowStack();
    printf("\t\t%c\t\t出栈、后移\n", st[current]);
   }
   else
   {
    printf("%c-%c不匹配!", analyseStack[topAnalyse], st[current]);
    printf("此串不是此文法的句子!\n");
    return;
   }
  }
  else /*当为非终结符时*/
  {
   r = analyseTable[analyseStack[topAnalyse] - 100][IndexCh(st[current])];
   if(-1 != r)
   {
    Push(r); /*产生式右部代替左部,指示器不移动*/
    step++;
    printf("%d\t", step);
    ShowStack();
    printf("\t\t%c\t\t%d\n", st[current], r);
   }
   else
   {
    printf("无可用产生式,此串不是此文法的句子!\n");
    return;
   }
  }
 }
 if('#' == st[current])
 {

  if(0 == topAnalyse && '#' == st[current])
  {
   step++;
   printf("%d\t", step);
   ShowStack();
   printf("\t\t%c\t\t分析成功!\n", st[current]);
   printf("%s是给定文法的句子!\n", st);
  }
  else
  {   while(topAnalyse > 0)
   {    if(100 > analyseStack[topAnalyse]) /*当为终结符时*/
    {     printf("无可用产生式,此串不是此文法的句子!\n");
     return;
    }
    else
    {     r = analyseTable[analyseStack[topAnalyse] - 100][vtNum];
     if(-1 != r)
     {      Push(r); /*产生式右部代替左部,指示器不移动*/
      step++;
      printf("%d\t", step);
      ShowStack();
      if(0 == topAnalyse && '#' == st[current])
      {       printf("\t\t%c\t\t分析成功!\n", st[current]);
       printf("%s是给定文法的句子!\n", st);
      }
      else      
       printf("\t\t%c\t\t%d\n", st[current], r);     }
     else
     {      printf("无可用产生式,此串不是此文法的句子!\n");
      return;     }
    }
   }
  }
 }
}
/*初始化栈及符号串*/
void InitStack()
{ int i;
 /*分析栈的初始化*/
 for(i = 0; i < MaxStLength; i++)
  st[i] = '\0';
 analyseStack[0] = -1; /*#(-1)入栈*/
 analyseStack[1] = 100; /*初始符入栈*/
 topAnalyse = 1;
}
/*显示符号栈中内容*/
void ShowStack()
{ int i;
 for(i = 0; i <= topAnalyse; i++)
 {  if(100 <= analyseStack[i])
   printf("%c", Vn[analyseStack[i] - 100]);
  else
  {   if(-1 != analyseStack[i])
    printf("%c", Vt[analyseStack[i]]);
   else
    printf("#");
  }
 


}
}
/*栈顶出栈*/
void Pop()
{ topAnalyse--;
}
/*使用产生式入栈操作*/
void Push(int r)
{ int i;
 struct pRNode *pt;
 Pop();
 pt = P[r].rHead;
 if(-1 == pt->rCursor) /*为空产生式时*/
  return;
 topAnalyse += P[r].rLength;
 for(i = 0; i < P[r].rLength; i++)
 {  /*不为空产生式时*/
  analyseStack[topAnalyse - i] = pt->rCursor;/*逆序入栈*/
  pt = pt->next;
 }/*循环未完时pt为空,则说明rLength记录等出错*/
}

【程序截图】

更多相关推荐:
用两种方法生成awr报告

u01apporacleproduct1120dbhome1rdbmsadminawrrptsql脚本生成awr报告在SQL环境执行SQLgtu01apporacleproduct1120dbhome1rdbm...

生成报告模板

溃坝风险分析软件报告一数据时间20xx0711130020xx0711190020xx0712010020xx0712070020xx0712130020xx0712190020xx0713010020xx07...

ANSYS HTML报告生成器

liusjANSYSHTML报告生成器ANSYS专利技术即基于WEB技术的报告生成技术为分析工程师带来了很大的方便这在ANSYS的DesignSpace和Professional中得到了很好的体现从ANSYS5...

ORACLE AWR报告生成步骤

ORACLEAWR报告生成步骤以PLSQL中命令窗口为例1sqlplus或plsql的commod窗口命令窗口运行命令Doracleproduct1020db1RDBMSADMINawrrptsql然后在弹出的...

ASH报告生成详解

1参看AWR报告生成详解doc2切换用户rootxlserver10suoracle注意后面有空格oracle为用户名3oraclexlserver10pwd4oraclexlserver10cdoptorac...

OracleAWR报告生成

oracle遇到性能问题时性能分析的一个思路就是导出AWR分析报告通过报告分析定位问题根源以下是oracle10g如何生成分析报告的步骤oracle10gAWR分析报告文件类型分为txt和html两种本人习惯使...

如何生成生成课题引文报告

无论是进行科研立项还是开题报告您常常需要从宏观上把握国内外某一研究领域或专题的总体研究趋势如何快速获取这些信息呢您可以通过生成课题引文报告或分析论文出版年的方式有效获得1访问WebofScience数据库检索论...

生成审计报告及附注的方法

生成审计报告及附注的逻辑关系1第一步在各个报表项目中将附注数据处理好比如应收票据如果要按票据类型列示就需要对应收票据按类型汇总并将数据填入附注中2项目初始gt报表附注管理及审计报告系统gt有打开新窗口的工具条执...

ORACLE_AWR报告生成

ORACLEAWR报告生成步骤以PLSQL中命令窗口为例1sqlplus或plsql的commod窗口命令窗口运行命令Doracleproduct1020db1RDBMSADMINawrrptsql然后在弹出的...

教你如何生成oracle的awrrpt报告

Oracle性能分析入门学习中遇到Oracle数据库的性能问题一般首要的步骤就是导出AWR的分析报告AWR是10g中新引入的一个工具在这之前一般是利用statspack要导出AWR报告只要利用Oracle的一个...

手工生成AWR报告方法记录

手工生成AWR报告方法记录20xx0622134946分类LinuxAWRAutomaticWorkloadRepository报告是我们进行日常数据库性能评定问题SQL发现的重要手段熟练掌握AWR报告是做好开...

计算机图形学 实验一直线生成算法报告

实验一直线生成算法一实验目的及要求1学习C语言的基本绘图方法2实习直线基本生成算法3了解光栅图形显示器的工作原理和特点4掌握课本所介绍的图形算法的原理和实现5基于光栅图形显示器在c环境中使用基本图形生成算法画根...

生成报告(36篇)