当前位置:文档之家› 编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验(java)
编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验

本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。

基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。若不为“#”且不与当前输入符号一样,则出错。

若栈顶符号为非终结符时,查看预测分析表,看栈顶符号和当前输入符号是否构成产生式,若产生式的右部为ε,则将栈顶符号出栈,取出栈顶符号进入下一个字符的分析。若不为ε,将产生式的右部逆序的入栈,取出栈顶符号进入下一步分析。

程序流程图:

本程序中使用以下文法作对用户输入的字符串进行分析:

E→TE’

E’→+TE’|ε

T→FT’

T’→*FT’|ε

F→i|(E)

该文法的预测分析表为:

1、显示预测分析表,提示用户输入字符串

2、输入的字符串为正确的句子:

3、输入的字符串中包含了不属于终结符集的字符

4、输入的字符串不是该文法能推导出来的句子

程序代码:

package https://www.doczj.com/doc/442610945.html,;

import java.io.*;

public class LL {

String Vn[] = { "E", "E'", "T", "T'", "F" }; // 非终结符集String Vt[] = { "i", "+", "*", "(", ")", "#" }; // 终结符集String P[][] = new String[5][6]; // 预测分析表

String fenxi[] ; // 分析栈

int count = 1; // 步骤

int count1 = 1;//’分析栈指针

int count2 = 0, count3 = 0;//预测分析表指针

String inputString = ""; // 输入的字符串

boolean flag;

public void setCount(int count, int count1, int count2, int count3){

this.count = count;

this.count1 = count1;

this.count2 = count2;

this.count3 = count3;

flag = false;

}

public void setFenxi() { // 初始化分析栈

fenxi = new String[20];

fenxi[0] = "#";

fenxi[1] = "E";

}

public void setP() { // 初始化预测分析表

for (int i = 0; i < 5; i++) {

for (int j = 0; j < 6; j++) {

P[i][j] = "error";

}

}

P[0][0] = "->TE'";

P[0][3] = "->TE'";

P[1][1] = "->+TE'";

P[1][4] = "->ε";

P[1][5] = "->ε";

P[2][0] = "->FT'";

P[2][3] = "->FT'";

P[3][1] = "->ε";

P[3][2] = "->*FT'";

P[3][4] = "->ε";

P[3][5] = "->ε";

P[4][0] = "->i";

P[4][3] = "->(E)";

// 打印出预测分析表

System.out.println(" 已构建好的预测分析表");

System.out.println("----------------------------------------------------------------------");

for (int i=0; i<6; i++) {

System.out.print(" "+Vt[i]);

}

System.out.println();

System.out.println("----------------------------------------------------------------------");

for (int i=0; i<5; i++) {

System.out.print(" "+Vn[i]+" ");

for (int j=0; j<6; j++) {

int l = 0;

if (j>0) {

l = 10-P[i][j-1].length();

}

for (int k=0; k

System.out.print(" ");

}

System.out.print(P[i][j]+" ");

}

System.out.println();

}

System.out.println("----------------------------------------------------------------------"); }

public void setInputString(String input) {

inputString = input;

}

public boolean judge() {

String inputChar = inputString.substring(0, 1); // 当前输入字符

boolean flage = false;

if (count1 >= 0) {

for (int i=0; i<6; i++) {

if (fenxi[count1].equals(Vt[i])) { // 判断分析栈栈顶的字符是否为终结符

flage = true;

break;

}

}

}

if (flage) {// 为终结符时

if (fenxi[count1].equals(inputChar)) {

if (fenxi[count1].equals("#")&&inputString.length()==1) { // 栈顶符号为结束标志时

// System.out.println("最后一个");

String fenxizhan = "";

for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)

if (fenxi[i] == null) {

break;

} else {

fenxizhan = fenxizhan + fenxi[i];

}

}

// 输出当前分析栈情况,输入字符串,所用产生式或匹配

System.out.print(" " + count);

String countToString = Integer.toString(count);

int farWay = 14 - countToString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(fenxizhan);

farWay = 20 - fenxizhan.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(inputString);

farWay = 25 - inputString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.println("接受");

flag = true;

return true;

} else {// 分析栈栈顶符号不为结束标志符号时

String fenxizhan = "";

for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)

if (fenxi[i] == null) {

break;

} else {

fenxizhan = fenxizhan + fenxi[i];

}

}

// 输出当前分析栈情况,输入字符串,所用产生式或匹配

System.out.print(" "+count);

String countToString = Integer.toString(count);

int farWay = 14 - countToString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(fenxizhan);

farWay = 20 - fenxizhan.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(inputString);

farWay = 25 - inputString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.println("\"" + inputChar + "\"" + "匹配");

// 将栈顶符号出栈,栈顶指针减一

fenxi[count1] = null;

count1 -= 1;

if (inputString.length() > 1) { // 当当前输入字符串的长度大于1时,将当前输入字符从输入字符串中除去

inputString = inputString.substring(1, inputString

.length());

} else { // 当前输入串长度为1时

inputChar = inputString;

}

// System.out.println(" "+count+" "+fenxizhan+"

// "+inputString +" "+P[count3][count2]);

// System.out.println(count + inputChar + "匹配");

count++;

judge();

}

}else { // 判断与与输入符号是否一样为结束标志

System.out.println(" 分析到第" + count + "步时出错!");

flag = false;

return false;

}

} else {

// 非终结符时

boolean fla = false;

for (int i=0; i<6; i++) { // 查询当前输入符号位于终结符集的位置if (inputChar.equals(Vt[i])) {

fla = true;

count2 = i;

break;

}

}

if(!fla){

System.out.println(" 分析到第" + count + "步时出错!");

flag = false;

return false;

}

for (int i=0; i<5; i++) { // 查询栈顶的符号位于非终结符集的位置if (fenxi[count1].equals(Vn[i])) {

count3 = i;

break;

}

}

if (P[count3][count2] != "error") { // 栈顶的非终结符与输入的终结符存在产生式时

String p = P[count3][count2];

String s1 = p.substring(2, p.length()); // 获取对应的产生式

if (s1.equals("ε")) { // 产生式推出“ε”时

String fenxizhan = "";

for (int i=0; i<=P.length; i++) {

if (fenxi[i] == null) {

break;

} else {

fenxizhan = fenxizhan + fenxi[i];

}

}

// 输出当前分析栈情况,输入字符串,所用产生式或匹配

System.out.print(" " + count);

String countToString = Integer.toString(count);

int farWay = 14 - countToString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(fenxizhan);

farWay = 20 - fenxizhan.length();

for (int k=0; k

System.out.print(" ");

}

System.out.print(inputString);

farWay = 25 - inputString.length();

for (int k=0; k

System.out.print(" ");

}

System.out.println(fenxi[count1] + P[count3][count2]);

// 将栈顶符号出栈,栈顶指针指向下一个元素

fenxi[count1] = null;

count1 -= 1;

count++;

judge();

} else { // 产生式不推出“ε”时

int k = s1.length();

String fenxizhan = "";

for (int i=0; i<=P.length; i++) {

if (fenxi[i] == null) {

break;

} else {

fenxizhan = fenxizhan + fenxi[i];

}

}

// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" "+count);

String countToString = Integer.toString(count);

int farWay = 14 - countToString.length();

for (int o=0; o

System.out.print(" ");

}

System.out.print(fenxizhan);

farWay = 20 - fenxizhan.length();

for (int o=0; o

System.out.print(" ");

}

System.out.print(inputString);

farWay = 25 - inputString.length();

for (int o=0; o

System.out.print(" ");

}

System.out.println(fenxi[count1] + P[count3][count2]);

for (int i=1; i<=k; i++) { // 将产生式右部的各个符号入栈String s2 = s1.substring(s1.length() - 1, s1.length());

s1 = s1.substring(0, s1.length() - 1);

if (s2.equals("'")) {

s2 = s1.substring(s1.length() - 1, s1.length())+ s2;

i++;

s1 = s1.substring(0, s1.length() - 1);

}

fenxi[count1] = s2;

if (i < k)

count1++;

// System.out.println("count1=" + count1);

}

// System.out.println(" "+count+" "+fenxizhan+"

// "+inputString +" "+P[count3][count2]);

count++;

// System.out.println(count);

judge();

}

} else {

System.out.println(" 分析到第" + count + "步时出错!");

flag = false;

return false;

}

}

return flag;

}

public static void main(String args[]) {

LL l = new LL();

l.setP();

String input = "";

boolean flag = true;

while (flag) {

try {

InputStreamReader isr = new InputStreamReader(System.in);

BufferedReader br = new BufferedReader(isr);

System.out.println();

System.out.print("请输入字符串(输入exit退出):");

input = br.readLine();

} catch (Exception e) {

e.printStackTrace();

}

if(input.equals("exit")){

flag = false;

}else{

l.setInputString(input);

l.setCount(1, 1, 0, 0);

l.setFenxi();

System.out.println();

System.out.println("分析过程");

System.out.println("----------------------------------------------------------------------");

System.out.println(" 步骤| 分析栈| 剩余输入串| 所用产生式");

System.out.println("----------------------------------------------------------------------");

boolean b = l.judge();

System.out.println("----------------------------------------------------------------------");

if(b){

System.out.println("您输入的字符串"+input+"是该文发的一个句子");

}else{

System.out.println("您输入的字符串"+input+"有词法错误!");

}

}

}

}

}

编译原理课程设计-词法语法分析器

编译原理课程设计Course Design of Compiling (课程代码3273526) 半期题目:词法和语法分析器 实验学期:大三第二学期 学生班级:2014级软件四班 学生学号:2014112218 学生姓名:何华均 任课教师:丁光耀 信息科学与技术学院 2017.6

课程设计1-C语言词法分析器 1.题目 C语言词法分析 2.内容 选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。 将解析到的单词符号对应的二元组输出到文件中保存 可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了 3.设计目的 掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解 4.设计环境(电脑语言环境) 语言环境:C语言 CPU:i7HQ6700 内存:8G 5.概要设计(单词符号表,状态转换图) 5.1词法分析器的结构 词法分析程序的功能:

输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词. 为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序: 1) ch 存放最新读进的源程序字符 2) strToken 存放构成单词符号的字符串 3) Buffer 字符缓冲区 4)struct keyType 存放保留字的符号和种别 5.2待分析的简单词法 (1)保留字 break、case、char、const、int、do、while… (2)运算符和界符 = 、+、-、* 、/、%、,、;、(、)、?、# 5.3各种单词符号对应的种别码

编译原理语法分析实验报告

编译原理语法分析实验报告 - 班级:XXX 学号:XXX 姓名:XXX 年月日 1、摘要: 用递归子程序法实现对pascal的子集程序设计语言的分析程序 2、实验目的: 通过完成语法分析程序,了解语法分析的过程和作用 3、任务概述 实验要求:对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用 4、实验依据的原理 递归子程序法是一种自顶向下的语法分析方法,它要求文法是LL(1)文法。通过对文法中每个非终结符编写一个递归过程,每个过程的功能是识别由该非终结符推出的串,当某非终结符的产生式有多个候选式时,程序能够按LL(1)形式唯一地确定选择某个候选式进行推导,最终识别输入串是否与文法匹配。 递归子程序法的缺点是:对文法要求高,必须满足LL(1)文法,当然在某些语言中个别产生式的推导当不满足LL(1)而满足LL(2)时,也可以采用多向前扫描一个符号的办法;它的另一个缺点是由于递归调用多,所以速度慢占用空间多,尽管这样,它还是许多高级语言,例如PASCAL,C等编译系统常常采用的语法分析方法。

为适合递归子程序法,对实验一词法分析中的文法改写成无左递归和无左共因子的,,,如下: <程序>?<程序首部><分程序>。 <程序首部>?PROGRAM标识符; <分程序>?<常量说明部分><变量说明部分><过程说明部分> <复合语句> <常量说明部分>?CONST<常量定义><常量定义后缀>;|ε <常量定义>?标识符=无符号整数 <常量定义后缀>?,<常量定义><常量定义后缀> |ε <变量说明部分>?VAR<变量定义><变量定义后缀> |ε <变量定义>?标识符<标识符后缀>:<类型>; <标识符后缀>?,标识符<标识符后缀> |ε <变量定义后缀>?<变量定义><变量定义后缀> |ε <类型>?INTEGER | LONG <过程说明部分>?<过程首部><分程序>;<过程说明部分后缀>|ε <过程首部>?PROCEDURE标识符<参数部分>; <参数部分>?(标识符: <类型>)|ε <过程说明部分后缀>?<过程首部><分程序>;<过程说明部分后缀>|ε <语句>?<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句> |<写语句>|<复合语句>|ε <赋值或调用语句>?标识符<后缀> <后缀>?:=<表达式>|(<表达式>)|ε <条件语句>?IF<条件>THEN<语句> <当型循环语句>?WHILE<条件>DO <语句> <读语句>?READ(标识符<标识符后缀>)

编译原理词法分析器语法分析器实验报告

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

编译原理-编写递归下降语法分析器

学号107 成绩 编译原理上机报告 名称:编写递归下降语法分析器 学院:信息与控制工程学院 专业:计算机科学与技术 班级:计算机1401班 姓名:叶达成 2016年10月31日

一、上机目的 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、基本原理和上机步骤 递归下降分析程序实现思想简单易懂。程序结构和语法产生式有直接的对应关系。因为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。 递归下降分析程序的实现思想是:识别程序由一组子程序组成。每个子程序对应于一个非终结符号。 每一个子程序的功能是:选择正确的右部,扫描完相应的字。在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。 自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。分析速度慢。而无回溯的自上向下分析技术,当选择某非终结符的产生时,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。 无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。 无左递归:既没有直接左递归,也没有间接左递归。 无回溯:对于任一非终结符号U的产生式右部x1|x2|…|x n,其对应的字的首终结符号两两不相交。 如果一个文法不含回路(形如P?+ P的推导),也不含以ε为右部的产生式,那么可以通过执行消除文法左递归的算法消除文法的一切左递归(改写后的文法可能含有以ε为右部的产生式)。 三、上机结果 测试数据: (1)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i# (2)输出结果:i+i*i#为合法符号串 (3)输入一符号串如i+i*#,要求输出为“非法的符号串”。 程序清单: #include #include char str[50]; int index=0; void E(); //E->TX; void X(); //X->+TX | e void T(); //T->FY void Y(); //Y->*FY | e void F(); //F->(E) | i int main() /*递归分析*/ { int len; int m;

编译原理实验报告(语法分析器)

. 编译原理实验专业:13级网络工程

语法分析器1 一、实现方法描述 所给文法为G【E】; E->TE’ E’->+TE’|空 T->FT’ T’->*FT’|空 F->i|(E) 递归子程序法: 首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。以分号作为结束符。 二、实现代码 头文件shiyan3.h #include #include

#include using namespace std; #define num 100 char vocabulary[num]; char *ch; void judge_E(); void judge_EE(); void judge_T(); void judge_TT(); void judge_F(); 源文件 #include"shiyan3.h" void judge_E() { if(*ch==';') { cout<<"该句子符合此文法!"<

int a=0; cout<<"按1结束程序"<>a; if(a==1) exit(0); } else if(*ch=='('||*ch=='i') { judge_T(); judge_EE(); } else { cout<<"该句子不匹配此文法!"<>a; if(a==1) exit(0); }

编译原理 语法分析器 (java完美运行版)(精选.)

实验二语法分析器 一、实验目的 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。有利于提高学生的专业素质,为培养适应社会多方面需要的能力。 二、实验内容 ◆根据某一文法编制调试LL (1 )分析程序,以便对任意输入的符号串 进行分析。 ◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分 析程序。 ◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号 以及LL(1)分析表,对输入符号串自上而下的分析过程。 三、LL(1)分析法实验设计思想及算法 ◆模块结构: (1)定义部分:定义常量、变量、数据结构。 (2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等); (3)控制部分:从键盘输入一个表达式符号串; (4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

四、实验要求 1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。 2、如果遇到错误的表达式,应输出错误提示信息。 3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG (2)G->+TG|—TG (3)G->ε (4)T->FS (5)S->*FS|/FS (6)S->ε (7)F->(E) (8)F->i 输出的格式如下:

五、实验源程序 LL1.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.sql.*; import java.util.Vector; public class LL1 extends JFrame implements ActionListener { /** * */ private static final long serialVersionUID = 1L; JTextField tf1; JTextField tf2; JLabel l; JButton b0; JPanel p1,p2,p3; JTextArea t1,t2,t3; JButton b1,b2,b3;

编译原理词法分析和语法分析报告 代码(C语言版)

词法分析 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3.1 主程序示意图: 扫描子程序主要部分流程图 其他

词法分析程序的C语言程序源代码: // 词法分析函数: void scan() // 数据传递: 形参fp接收指向文本文件头的文件指针; // 全局变量buffer与line对应保存源文件字符及其行号,char_num保存字符总数。 void scan() { char ch; int flag,j=0,i=-1; while(!feof(fp1)) { ch=fgetc(fp1); flag=judge(ch); printf("%c",ch);//显示打开的文件 if(flag==1||flag==2||flag==3) {i++;buffer[i]=ch;line[i]=row;} else if(flag==4) {i++;buffer[i]='?';line[i]=row;} else if(flag==5) {i++;buffer[i]='~';row++;} else if(flag==7) continue; else cout<<"\n请注意,第"<

编译原理实验三-自下而上语法分析及语义分析.docx

上海电力学院 编译原理 课程实验报告 实验名称:实验三自下而上语法分析及语义分析 院系:计算机科学和技术学院 专业年级: 学生姓名:学号: 指导老师: 实验日期: 实验三自上而下的语法分析 一、实验目的: 通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。 二、实验学时: 4学时。 三、实验内容

根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。 对于正确的表达式,给出表达式的值。 对于错误的表达式,给出出错位置。 四、实验方法 采用LR分析法。 首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。 接下来给出LR分析表。 然后程序的具体实现: ● LR分析表可用二维数组(或其他)实现。 ●添加一个val栈作为语义分析实现的工具。 ●编写总控程序,实现语法分析和语义分析的过程。 注:对于整数的识别可以借助实验1。 五、文法定义 简单的表达式文法如下: (1)E->E+T (2)E->E-T (3)E->T

(4)T->T*F (5)T->T/F (6)T->F (7)F->(E) (8)F->i 状态ACTION(动作)GOTO(转换) i + - * / ( ) # E T F 0 S5 S4 1 2 3 1 S6 S1 2 acc 2 R 3 R3 S7 S13 R3 R3 3 R6 R6 R6 R6 R6 R6 4 S 5 S4 8 2 3 5 R8 R8 R8 R8 R8 R8 6 S5 S4 9 3 7 S5 S4 10 8 S6 R12 S11 9 R1 R1 S7 S13 R1 R1 10 R4 R4 R4 R4 R4 R4 11 R7 R7 R7 R7 R7 R7 12 S5 S4 14 3 13 S5 S4 15 14 R2 R2 S7 S13 R2 R2 15 R5 R5 R5 R5 R5 R5 五、处理程序例和处理结果例 示例1:20133191*(20133191+3191)+ 3191#

编译原理-语法分析-算符优先文法分析器

编译原理实验报告 实验名称:编写语法分析分析器实验类型: 指导教师: 专业班级: 学号: 电子邮件: 实验地点: 实验成绩:

一、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,至少选一题。 2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。 二、实验过程 编写算符优先分析器。要求: (a)根据算符优先分析算法,编写一个分析对象的语法分析程序。读者可根据自己的能力选择以下三项(由易到难)之一作为分析算法中的输入: Ⅰ:通过构造算符优先关系表,设计编制并调试一个算法优先分析程序Ⅱ:输入FIRSTVT,LASTVT集合,由程序自动生成该文法的算符优先关系矩阵。 Ⅲ:输入已知文法,由程序自动生成该文法的算符优先关系矩阵。(b)程序具有通用性,即所编制的语法分析程序能够使用于不同文法以及各种输入单词串,并能判断该文法是否为算符文法和算符优先文法。 (c)有运行实例。对于输入的一个文法和一个单词串,所编制的语法分析程序应能正确地判断,此单词串是否为该文法的句子,并要求输出分析过程。 三、实验结果 算符优先分析器: 测试数据:E->E+T|T T->T*F|F F->(E)|i 实验结果:(输入串为i+i*i+i)

四、讨论与分析 自下而上分析技术-算符优先分析法: 算符文法:一个上下无关文法G,如果没有且没有P→..QR...(P ,Q ,R属于非终结符),则G是一个算符文法。 FIRSTVT集构造 1、若有产生式P →a...或P →Qa...,则a∈FIRSTVT(P)。 2、若有产生式P→...,则FIRSTVT(R)包含在FIRSTVT(P)中。由优先性低于的定义和firstVT集合的定义可以得出:若存在某个产生式:…P…,则对所有:b∈firstVT(P)都有:a≦b。 构造优先关系表: 1、如果每个非终结符的FIRSTVT和LASTVT集均已知,则可构造优先关系表。 2、若产生式右部有...aP...的形式,则对于每个b∈FIRSTVT(P)都有

编译原理语法分析器实验

语法分析器的设计 一、实验内容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

编译原理实验报告

《编译原理》 实验报告 姓名:余同庆 班级:软件1005班 学号: 3902100509 日期: 2012-6-7 中南大学软件学院 2012年06月

第一部分词法分析 词法分析程序设计与实现 一、实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 二、实验内容 自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。词法分析程序的实现可以采用任何一种编程语言和编程工具。 从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 三、实验要求 1.对单词的构词规则有明确的定义; 2.编写的分析程序能够正确识别源程序中的单词符号; 3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护 符号表; 4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误 提示,保证顺利完成整个源程序的词法分析; 四、程序设计思路 这里以开始定义的C语言子集的源程序作为词法分析程序的输入数据。在词法分析中,自文件头开始扫描源程序字符,一旦发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查、填适当的信息表。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。 1.定义部分:定义常量、变量、数据结构。 2.初始化:从文件将源程序全部输入到字符缓冲区中。 3.取单词前:去掉多余空白。 4.取单词:利用实验一的成果读出单词的每一个字符,组成单词,分析类

昆明理工大学 编译原理 实验二 语法分析器

昆明理工大学信息工程与自动化学院学生实验报告 (2011 —2012 学年第 1 学期) 课程名称:编译原理开课实验室: 445 2011年 12 月 19日年级、专业、 班 计科093 学号200910405310 姓名孙浩川成绩 实验项目名称语法分析器指导教师严馨 教 师评语 该同学是否了解实验原理: A.了解□ B.基本了解□ C.不了解□ 该同学的实验能力: A.强□ B.中等□ C.差□ 该同学的实验是否达到要求: A.达到□ B.基本达到□ C.未达到□ 实验报告是否规范: A.规范□ B.基本规范□ C.不规范□ 实验过程是否详细记录: A.详细□ B.一般□ C.没有□ 教师签名: 年月日 一、实验目的及内容 实验目的:编制一个语法分析程序,实现对词法分析程序所提供的单词序列进行语法检 查和结构分析。 实验内容:在上机(一)词法分析的基础上,采用递归子程序法或其他适合的语法分析方法,实现其语法分析程序。要求编译后能检查出语法错误。 已知待分析的C语言子集的语法,用EBNF表示如下: <程序>→main()<语句块> <语句块> →‘{’<语句串>‘}’ <语句串> → <语句> {; <语句> }; <语句> → <赋值语句> |<条件语句>|<循环语句> <赋值语句>→ID=<表达式>

<条件语句>→if‘(‘条件’)’<语句块> <循环语句>→while’(‘<条件>’)‘<语句块> <条件> → <表达式><关系运算符> <表达式> <表达式> →<项>{+<项>|-<项>} <项> → <因子> {* <因子> |/ <因子>} <因子> →ID|NUM| ‘(’<表达式>‘)’ <关系运算符> →<|<=|>|>=|==|!= 二、实验原理及基本技术路线图(方框原理图或程序流程图)

编译原理语法分析器实验报告

编译原理语法分析器实验报告

西安邮电大学 编译原理实验报告 学院名称:计算机学院 学生姓名:高宏伟 实验名称:语法分析器的设计与实现班级:计科1405班学号:04141152 时间:2017年5月12日

把SELECT (i)存放到temp中结果返回1; 1.构建好的预测分析表 2.语法分析流程图 一.实验结果 正确运行结果:

错误运行结果: 二.设计技巧和心得体会 这次实验编写了一个语法分析方法的程序,但是在LL(1)分析器的编写中我只达到了最低要求,就是自己手动输入的select集,first集,follow集然后通过程序将预测分析表构造出来,然后自己编写总控程序根据分析表进行分析。 通过本次试验,我能够设计一个简单的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 还能选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析

程序和LR分析分析程序。 三.源代码 package com.LL1; import java.util.ArrayDeque; import java.util.Deque; /** * LL1文法分析器,已经构建好预测分析表,采用Deque实现 * Created by HongWeiPC on 2017/5/12. */ public class LL1_Deque { //预测分析表 private String[][] analysisTable = new String[][]{ {"TE'", "", "", "TE'", "", ""}, {"", "+TE'", "", "", "ε", "ε"}, {"FT'", "", "", "FT'", "", ""}, {"", "ε", "*FT'", "", "ε", "ε"}, {"i", "", "", "(E)", "", ""} }; //终结符 private String[] VT = new String[]{"i", "+", "*", "(", ")", "#"}; //非终结符 private String[] VN = new String[]{"E", "E'", "T", "T'", "F"}; //输入串strToken private StringBuilder strToken = new StringBuilder("i*i+i"); //分析栈stack private Deque stack = new ArrayDeque<>(); //shuru1保存从输入串中读取的一个输入符号,当前符号 private String shuru1 = null; //X中保存stack栈顶符号 private String X = null; //flag标志预测分析是否成功 private boolean flag = true; //记录输入串中当前字符的位置 private int cur = 0; //记录步数 private int count = 0; public static void main(String[] args) { LL1_Deque ll1 = new LL1_Deque(); ll1.init(); ll1.totalControlProgram(); ll1.printf(); } //初始化 private void init() { strToken.append("#"); stack.push("#"); System.out.printf("%-8s %-18s %-17s %s\n", "步骤", "符号栈", "输入串", "所用产生式"); stack.push("E"); curCharacter(); System.out.printf("%-10d %-20s %-20s\n", count, stack.toString(), strToken.substring(cur, strToken.length())); } //读取当前栈顶符号 private void stackPeek() { X = stack.peekFirst(); } //返回输入串中当前位置的字母 private String curCharacter() { shuru1 = String.valueOf(strToken.charAt(cur)); return shuru1; } //判断X是否是终结符 private boolean XisVT() { for (int i = 0; i < (VT.length - 1); i++) { if (VT[i].equals(X)) {

编译原理实验二语法分析器LL(1)实现

编译原理程序设计实验报告 ——表达式语法分析器的设计班级:计算机1306班:涛学号:20133967 实验目标:用LL(1)分析法设计实现表达式语法分析器 实验容: ⑴概要设计:通过对实验一的此法分析器的程序稍加改造,使其能够输出正确的表达式的token序列。然后利用LL(1)分析法实现语法分析。 ⑵数据结构: int op=0; //当前判断进度 char ch; //当前字符 char nowword[10]=""; //当前单词 char operate[4]={'+','-','*','/'}; //运算符 char bound[2]={'(',')'}; //界符 struct Token { int code; char ch[10]; }; //Token定义

struct Token tokenlist[50]; //Token数组struct Token tokentemp; //临时Token变量struct Stack //分析栈定义 { char *base; char *top; int stacksize; }; ⑶分析表及流程图

逆序压栈 int IsLetter(char ch) //判断ch是否为字母 int IsDigit(char ch) //判断ch是否为数字 int Iskey(char *string) //判断是否为关键字 int Isbound(char ch) //判断是否为界符 int Isboundnum(char ch) //给出界符所在token值int init(STack *s) //栈初始化 int pop(STack *s,char *ch) //弹栈操作 int push(STack *s,char ch) //压栈操作 void LL1(); //分析函数 源程序代码:(加入注释)

编译原理语法分析实验报告.

编译原理语法分析实验报告 02282021 赖荣凤 1.实验目的 编写一语法分析器,锻炼团队工作能力 2.实验环境 Windows XP VC++6.0 3.实验内容 这次实验中我的任务就是:设计程序框架,制定编译器文法,作出状态转换图并编写部分程序代码。 这次实验任务较重,为了更好组织大家一起动手实验,由我和黄曙丰统一策划这次实验安排。 我们用递归下降分析方法,为每一标识符编写一分析子程序。 我跟黄曙丰先制定了本编译器的32条文法规则。 SmartC语言的EBNF文法规则语法: 1. program -> declaration-list 2. declaration-list -> declaration { declaration } 3. declaration -> var-declaration | fun-declaration 4. var-declaration -> type-specifier ID ; | type-specifier ID [ NUM ] ; 5. type-specifier -> int | void 6. fun-declaration -> type-specifier ID ( params ) compound-stmt 7. params -> params-list | void 8. param-list -> param { , param } 9. param -> type-specifier ID | type-specifier ID [ ] 10. compound-stmt -> { local-declarations statement-list} (注:该处左右大括号是真正意义上的大括号) 11. local-declarations -> var-declaration { var-declaration }| empty 12. statement-list -> statement { statement }| empty 13. statement -> expression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmt 14. expression-stmt -> expression ; | ; 15. selection-stmt -> if ( expression ) statement [ else statement ] (注:该处左右中括号是唯一表示内容可选的中括号) 16. iteration-stmt -> while ( expression ) statement |for(expression;expression;expression) statement 17. return-stmt -> return ; | return expression; 18. expression -> var = expression | simple-expression|logical-expression 19. var -> ID | ID [value] 20. simple-expression -> additive-expression relop additive-expression | additive-expression 21. logical-expression-> simple-expression logical simple-expression {logical logical-expression}| ! simple-expression {logical logical-expression} 22 logical-> &&| || 23. relop -> <= | >= | < | > | == | != 24. additive-expression -> term { addop term } 25. addop -> + | - 26. term -> factor { mulop factor } 27. mulop -> * | / 28. factor -> ( simple-expression )|(logical-expression) | value 29. value->var | call | NUM 30. call -> ID ( args ) 31. args -> { arg-list } 32. arg-list -> expression { , expression } 然后由我根据这些文法规则画出了本编译器的状态转换图,并确定各标识符的First集和Follow 集。

编译原理实验报告《LL(1)语法分析器构造》

《LL(1)分析器的构造》实验报告 一、实验名称 LL(1)分析器的构造 二、实验目的 设计、编制、调试一个LL(1)语法分析器,利用语法分析器对符号串的识别,加深对语法分析原理的理解。 三、实验内容和要求 设计并实现一个LL(1)语法分析器,实现对算术文法: G[E]:E->E+T|T T->T*F|F F->(E)|i 所定义的符号串进行识别,例如符号串i+i*i为文法所定义的句子,符号串ii+++*i+不是文法所定义的句子。 实验要求: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。 四、主要仪器设备 硬件:微型计算机。 软件: Code blocks(也可以是其它集成开发环境)。

五、实验过程描述 1、程序主要框架 程序中编写了以下函数,各个函数实现的作用如下: void input_grammer(string *G);.Xn的FIRST集 string** create_table(string *P,string U,string u,int n,int t,int k,string* first);ppend(1,a) U=u=" ";mpty();n++) { U[n]=G[n][0]; }ength();j++) { if(G[i][j])==string::npos&&(G[i][j])==string::npos) if(G[i][j]!='|'&&G[i][j]!='^') ength();j++) { P[k][0]=U[i];P[k][1]=':';P[k][2]=':';P[k][3]='='; /* if(G[i][j]=='(') { j++;flag=1; for(temp=j;G[i][temp]!=')';temp++); C=G[i][temp+1]; ppend(1,U[i]);GG[m].append("::="); if('|')!=string::npos) GG[m].append("("+beta+")"); else GG[m].append(beta); while(C)!=string::npos){C++;} GG[m].append(1,C); m++; GG[m].append(1,C);GG[m].append("::="); if('|')!=string::npos) GG[m].append("("+arfa+")"); else GG[m].append(arfa); GG[m].append(1,C);GG[m].append("|^"); m++; C++; }ind('^')==string::npos) first[r].append(1,'^');ind(a)==string::npos)ppend(1,a); break;.Yk

编译原理实验-(词法语法分析-附源代码

编译原理实验报告 ******************************************************************************* ******************************************************************************* PL0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。PL/0语言文法的EBNF表示如下: <程序>::=<分程序>. <分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句> <常量说明> ::=CONST<常量定义>{,<常量定义>}; <常量定义> ::=<标识符>=<无符号整数> <无符号整数> ::= <数字>{<数字>} 】 <变量说明> ::=VAR <标识符>{, <标识符>}; <标识符> ::=<字母>{<字母>|<数字>} <过程说明> ::=<过程首部><分程序>{; <过程说明> }; <过程首部> ::=PROCEDURE <标识符>; <语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句> |<复合语句>|<读语句><写语句>|<空> <赋值语句> ::=<标识符>:=<表达式> <复合语句> ::=BEGIN <语句> {;<语句> }END <条件语句> ::= <表达式> <关系运算符> <表达式> |ODD<表达式> <表达式> ::= [+|-]<项>{<加法运算符> <项>} ; <项> ::= <因子>{<乘法运算符> <因子>} <因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’ <加法运算符> ::= +|- <乘法运算符> ::= *|/ <关系运算符> ::= =|#|<|<=|>|>= <条件语句> ::= IF <条件> THEN <语句> <过程调用语句> ::= CALL 标识符 <当循环语句> ::= WHILE <条件> DO <语句> <读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’ <写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’ ¥ <字母> ::= a|b|…|X|Y|Z <数字> ::= 0|1|…|8|9 【预处理】 对于一个pl0文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。

相关主题
文本预览
相关文档 最新文档