语法分析器的设计

合集下载

语法分析程序的设计与实现

语法分析程序的设计与实现

◆词法分析 用户必须提供一个词法分析器来读取输入流并把记号(带有值, 如果需要的话)传达到解析器。词法分析器使叫做 yylex 的整数值的 函数。这个函数返回一个整数的记号编号,它表示读取的记号的种类。 如果这个记号关联着一个值,应当把它赋予外部变量 yylval。 为使通信得以发生,解析器和词法分析器必须在记号编号上达成 一致。编号可以由 Yacc 或用户来选择。在这两种情况下,使用 C 语 言的“# define”机制允许词法分析器使用符号来返回这些编号。例如, 假定在 Yacc 规定文件的声明段中已经定义记号名字 DIGIT。 它的意图是返回一个 DIGIT 记号编号,和等于这个数字的数值 的一个值。倘若词法分析器代码位于规定文件的程序段,标识符 DIGIT 将被定义为与记号 DIGIT 关联的记号编号。 这种机制导致清晰的、易于修改的词法分析器;唯一的缺点是在 文法中需要避免使用任何在 C 语言或解析器中保留的或有意义的记 号名字;例如,使用记号名字 if 或 while 就一定会导致编译词法分 析器时出现严峻的困难。记号名字 error 保留给错误处理,不应该随 便使用。 同上所述,记号编号可以由 Yacc 或用户来选择。在缺省的条件 下,编号由 Yacc 选择。文字字符的缺省记号编号是它在本地字符集 中的字符数值。其他名字赋予从 257 开始的记号编号。 要把一个记号编号赋予一个记号(包括文字),可以在声明段中记 号或文字的第一次出现时直接跟随着一个非负整数。这个整数被接受
第四:YACC 内部名称: ................................................................................................ 7 第五:运行结果(源代码见附录).............................................................................. 8 第六:实验总结 ............................................................................................................... 8 第七:附录 ..................................................................................................................... 10

PL0语言语法分析器实验报告

PL0语言语法分析器实验报告

PL0语言语法分析器实验报告一、引言编译器是一种用于把高级语言程序转换成机器可执行代码的软件工具。

编译器由多个组件构成,其中语法分析器是编译器中的重要组成部分,其主要功能是对输入的源代码进行解析,并生成一个语法树。

本实验旨在通过使用BNF(巴科斯范式)描述PL0语言的语法规则,并通过实现PL0语言的语法分析器,来深入理解语法分析的原理和过程。

二、PL0语言的语法规则1.程序结构:<程序>::=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>2.常量说明部分:<常量说明部分> ::= const <常量定义> { , <常量定义> };<常量定义>::=<标识符>=<无符号整数>3.变量说明部分:<变量说明部分> ::= var <标识符> { , <标识符> };4.过程说明部分:<过程说明部分>::=<过程首部><分程序>;<过程首部> ::= procedure <标识符> ;5.语句:<语句> ::= <赋值语句> , <if语句> , <while语句> , <调用语句> , <复合语句> , <读语句> , <写语句> , <空><赋值语句>::=<标识符>:=<表达式><if语句> ::= if <条件> then <语句> else <语句><while语句> ::= while <条件> do <语句><调用语句> ::= call <标识符><复合语句> ::= begin <语句> { ; <语句> } end<读语句> ::= read ( <标识符> )<写语句> ::= write ( <表达式> )6.表达式:<表达式>::=[+,-]<项>{(+,-)<项>}<项>::=<因子>{(*,/)<因子>}<因子>::=<标识符>,<无符号整数>,(<表达式>)7.条件:<条件>::=<表达式><关系运算符><表达式><关系运算符>::==,<>,<,<=,>,>=三、PL0语言的语法分析器设计与实现1.设计思路本次实验中,我们将使用自顶向下的递归下降分析法,来对PL0语言进行语法分析。

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

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

《编译原理词法分析器语法分析课程设计-《编译原理》课程设计院系信息科学与技术学院专业软件工程年级级学号 2723姓名林苾湲西南交通大学信息科学与技术学院12月目录课程设计1 词法分析器 (2)设计题目 (2)设计内容 (2)设计目的 (2)设计环境 (2)需求分析 (2)概要设计 (2)详细设计 (4)编程调试 (5)测试 (11)结束语 (13)课程设计2 赋值语句的解释程序设计 (14)设计题目 (14)设计内容 (14)设计目的 (14)设计环境 (14)需求分析 (15)概要设计 (16)详细设计 (16)编程调试 (24)测试 (24)结束语 (25)课程设计一词法分析器设计一、设计题目手工设计c语言的词法分析器(能够是c语言的子集)。

二、设计内容处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。

三、设计目的了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。

四、设计环境该课程设计包括的硬件和软件条件如下:.硬件(1)Intel Core Duo CPU P8700(2)内存4G.软件(1)Window 7 32位操作系统(2)Microsoft Visual Studio c#开发平台.编程语言C#语言五、需求分析.源程序的预处理:源程序中,存在许多编辑用的符号,她们对程序逻辑功能无任何影响。

例如:回车,换行,多余空白符,注释行等。

在词法分析之前,首先要先剔除掉这些符号,使得词法分析更为简单。

.单词符号的识别并判断单词的合法性:将每个单词符号进行不同类别的划分。

单词符号能够划分成5中。

(1)标识符:用户自己定义的名字,常量名,变量名和过程名。

(2)常数:各种类型的常数。

(3) 保留字(关键字):如if、else、while、int、float 等。

(4) 运算符:如+、-、*、<、>、=等。

语法分析器实验报告

语法分析器实验报告

词法分析器实验报告实验名称:语法分析器实验内容:利用LL(1)或LR(1)分析语句语法,判断其是否符合可识别语法。

学会根据状态变化、first、follow或归约转移思想构造状态分析表,利用堆栈对当前内容进行有效判断实验设计:1.实现功能可对一段包含加减乘除括号的赋值语句进行语法分析,其必须以$为终结符,语句间以;隔离,判断其是否符合语法规则,依次输出判断过程中所用到的产生式,并输出最终结论,若有错误可以报错并提示错误所在行数及原因2.实验步骤3.算法与数据结构a)LLtable:left记录产生式左端字符;right记录产生式右端字符;ln记录产生式右端字符长度Status:记录token分析情况Token:category,类型;value,具体内容b)根据LL(1)算法,手工构造分析表,并将内容用数组存储,便于查找c)先将当前语句的各token按序存储,当前处理语句最后一个token以#标记,作为输入流与产生式比较,堆栈中初始放入#,x,a为处理输入流中当前读头内容✓若top=a=‘#‘表示识别成功,退出分析程序✓若top=a!=‘#‘表示匹配,弹出栈顶符号,读头前进一个✓若top为i或n,但top!=a,出错,输出当前语句所在行,出错具体字符✓若top不为i或n,查预测分析表,若其中存放关于top产生式,则弹出top,将产生式右部自右向左压入栈内,输出该产生式,若其中没有产生式,出错,输出当前语句所在行,出错具体字符d)以;作为语句终结,每次遇到分号则处理之前语句并清空后预备下语句处理,当遇到$表示该段程序结束,停止继续处理4.分析表构造过程a)x->i=ee->e+t|e-t|tt->t*f|t/f|ff->(e)|i|nnote: i表示变量,n表示数字,!表示空串b)提取左公因子x->i=ee->ea|ta->+t|-tt->tb|fb->*f|/ff->(e)|i|nc)消除左递归x->i=ee->tcc->ac|!a->+t|-tt->fdd->bd|!b->*e|/ff->(e)|i|n5.类class parser{public:LLtable table[100][100]; //LL(1)表void scanner(); //扫描输入流中内容并分析parser(istream& in); //初始化,得到输入文件地址int getLine() const; //得到当前行数private:int match(); //分析语法stack <char> proStack; //分析堆栈void constructTable(); //建立LL(1)表int getRow(char ch); //取字符所在表中行int getCol(char ch); //取字符所在表中列istream* pstream; //输入流void insertToken(token& t); //插入当前tokenstatus getToken(token& t); //找到tokenint getChar(); //得到当前字符int peekChar(); //下一个字符void putBackChar(char ch); //将字符放回void skipChar(); //跳过当前字符void initialization(); //初始化堆栈等int line; //当前行数token tokens[1000]; //字符表int counter; //记录当前字符表使用范围}6.主要代码void parser::constructTable() //建立LL(1)表{for (int i=0;i<8;i++){for (int j=0;j<9;j++){table[i][j].left=' ';for (int k=0;k<3;k++)table[i][j].right[k]=' ';}}table[0][6].left='x';table[0][6].ln=3;table[0][6].right[0]='i';table[0][6].right[1]='=';table[0][6].right[2]='e';table[1][4].left='e';table[1][4].ln=2;table[1][4].right[0]='t';table[1][4].right[1]='c';table[1][6].left='e';table[1][6].ln=2;table[1][6].right[0]='t';table[1][6].right[1]='c';table[1][7].left='e';table[1][7].ln=2;table[1][7].right[0]='t';table[1][7].right[1]='c';table[2][0].left='c';table[2][0].ln=2;table[2][0].right[0]='a';table[2][0].right[1]='c';table[2][1].left='c';table[2][1].ln=2;table[2][1].right[0]='a';table[2][1].right[1]='c';table[2][5].left='c';table[2][5].ln=0;table[2][5].right[0]='!';table[2][8].left='c';table[2][8].ln=0;table[2][8].right[0]='!';table[3][0].left='a';table[3][0].ln=2;table[3][0].right[0]='+'; table[3][0].right[1]='t'; table[3][1].left='a';table[3][1].ln=2;table[3][1].right[0]='-'; table[3][1].right[1]='t'; table[4][4].left='t';table[4][4].ln=2;table[4][4].right[0]='f'; table[4][4].right[1]='d'; table[4][6].left='t';table[4][6].ln=2;table[4][6].right[0]='f'; table[4][6].right[1]='d'; table[4][7].left='t';table[4][7].ln=2;table[4][7].right[0]='f'; table[4][7].right[1]='d'; table[5][0].left='d';table[5][0].ln=0;table[5][0].right[0]='!'; table[5][1].left='d';table[5][1].ln=0;table[5][1].right[0]='!'; table[5][2].left='d';table[5][2].ln=2;table[5][2].right[0]='b'; table[5][2].right[1]='d'; table[5][3].left='d';table[5][3].ln=2;table[5][3].right[0]='b'; table[5][3].right[1]='d'; table[5][5].left='d';table[5][5].ln=0;table[5][5].right[0]='!'; table[5][8].left='d';table[5][8].ln=0;table[5][8].right[0]='!'; table[6][2].left='b';table[6][2].ln=2;table[6][2].right[0]='*'; table[6][2].right[1]='f'; table[6][3].left='b';table[6][3].ln=2;table[6][3].right[0]='/'; table[6][3].right[1]='f'; table[7][4].left='f';table[7][4].ln=3;table[7][4].right[0]='(';table[7][4].right[1]='e';table[7][4].right[2]=')';table[7][6].left='f';table[7][6].ln=1;table[7][6].right[0]='i';table[7][7].left='f';table[7][7].ln=1;table[7][7].right[0]='n';}int parser::match() //分析语法{ofstream ofs("out.txt",ios::app);char a;int i=0;for (int p=0;p<counter;p++){cout<<tokens[p].value;ofs<<tokens[p].value;}cout<<endl;ofs<<endl<<"ANALYSIS:"<<endl;while(1){if(tokens[i].category=='n' || tokens[i].category=='i')a=tokens[i].category;elsea=(tokens[i].value)[0];if(a==proStack.top()){if(a=='#'){cout<<"This is valid!"<<endl<<endl;ofs<<"This is valid!"<<endl<<endl;return 0;}else{proStack.pop();i++;}}else{if(proStack.top() =='n'|| proStack.top() =='i'){if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}else{if((table[getRow(proStack.top())][getCol(a)]).left!=' '){char pst=proStack.top();int n=table[getRow(pst)][getCol(a)].ln;int k=0;ofs<<table[getRow(pst)][getCol(a)].left<<"->"<<table[getRow(pst)][getCol(a)].right[0]<<table[getRow(pst)][g etCol(a)].right[1]<<table[getRow(pst)][getCol(a)].right[2]<<endl;proStack.pop();while (n>0){//cout<<n<<" "<<table[getRow(pst)][getCol(a)].right[n-1]<<endl;proStack.push(table[getRow(pst)][getCol(a)].right[n-1]);n--;}}else{if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}}}}}实验结果:●输入(in.txt)●输出1输出2(out.txt)实验总结:原本以为处理四则运算赋值将会很困难,但在使用LL(1)后发现,思路还是挺清晰简单的,但在实验过程中,由于LL(1)不能出现左递归和左公因子,不得不将其消除,原本简单的产生式一下变多了,而在产生式理解上也没有原来直观,不过其状态复杂度没有LR高,故仍选择该方法。

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

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

编译原理语法分析器实验报告西安邮电大学编译原理实验报告学院名称:计算机学院****:***实验名称:语法分析器的设计与实现班级:计科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"};//输入串strTokenprivate StringBuilder strToken = new StringBuilder("i*i+i");//分析栈stackprivate Deque<String> 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)) {return true;}}return false;}//查找X在非终结符中分析表中的横坐标private String VNTI() {int Ni = 0, Tj = 0;for (int i = 0; i < VN.length; i++) {if (VN[i].equals(X)) {Ni = i;}}for (int j = 0; j < VT.length; j++) {if (VT[j].equals(shuru1)) {Tj = j;}}return analysisTable[Ni][Tj];}//判断M[A,a]={X->X1X2...Xk}//把X1X2...Xk推进栈//X1X2...Xk=ε,不推什么进栈private boolean productionType() {return VNTI() != "";}//推进stack栈private void pushStack() {stack.pop();String M = VNTI();String ch;//处理TE' FT' *FT'特殊情况switch (M) {case "TE'":stack.push("E'");stack.push("T");break;case "FT'":stack.push("T'");stack.push("F");break;case "*FT'":stack.push("T'");stack.push("F");stack.push("*");break;case "+TE'":stack.push("E'");stack.push("T");stack.push("+");break;default:for (int i = (M.length() - 1); i >= 0; i--) {ch = String.valueOf(M.charAt(i));stack.push(ch);}break;}System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, M);}//总控程序private void totalControlProgram() {while (flag) {stackPeek(); //读取当前栈顶符号令X=栈顶符号if (XisVT()) {if (X.equals(shuru1)) {cur++;shuru1 = curCharacter();stack.pop();System.out.printf("%-10d %-20s %-20s \n", (++count), stack.toString(), strToken.substring(cur, strToken.length()));} else {ERROR();}} else if (X.equals("#")) {if (X.equals(shuru1)) {flag = false;} else {ERROR();}} else if (productionType()) {if (VNTI().equals("")) {ERROR();} else if (VNTI().equals("ε")) {stack.pop();System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, VNTI());} else {pushStack();}} else {ERROR();}}}//出现错误private void ERROR() {System.out.println("输入串出现错误,无法进行分析");System.exit(0);}//打印存储分析表private void printf() {if (!flag) {System.out.println("****分析成功啦!****");} else {System.out.println("****分析失败了****");}}}。

语法分析器设计实验报告

语法分析器设计实验报告

语法分析器设计实验报告一、引言语法分析器是编译器中的重要组成部分,其主要功能是根据给定的文法规则,对输入的程序代码进行语法分析,判断其是否符合语法规范。

本实验旨在设计一个简单的语法分析器,通过实际实现一个基于LL(1)文法的语法分析器,深入了解语法分析的原理和实现方法。

二、实验目标本实验的目标是设计一个能够接受一个输入的程序代码并进行语法分析的程序。

具体而言,需要实现以下功能:1. 构建一个文法规则集合,用于描述程序代码的语法规范;2. 设计并实现一个LL(1)分析表,用于存储语法分析所需的预测分析表;3. 实现语法分析器,能够根据输入的程序代码,逐步地进行语法分析,并输出相应的结果。

三、实验环境本实验使用的是Java语言进行实现,操作系统环境为Windows 10。

使用的集成开发环境为Eclipse。

四、实验步骤1. 设计文法规则集合在语法分析器设计中,首先需要设计一个文法规则集合,用于描述需要分析的程序代码的语法规范。

文法规则集合的设计要符合LL(1)文法的要求,即每个非终结符的产生式至多有一个与输入符号串首符号相关的产生式。

2. 构建LL(1)分析表根据文法规则集合,构建一个LL(1)分析表,用于存储语法分析所需的预测分析表。

LL(1)分析表是一个二维表,其中行表示非终结符,列表示终结符。

表中的每个元素表示相应的产生式编号,用于指示语法分析器在分析过程中应该使用哪个产生式。

构建LL(1)分析表的方法包括:- 遍历文法规则集合,计算每个非终结符的FIRST集合和FOLLOW集合;- 根据计算得到的FIRST集合和FOLLOW集合,填充LL(1)分析表。

3. 实现语法分析器根据LL(1)分析表,实现一个语法分析器。

语法分析器的输入是一个程序代码,输出是语法分析器的分析结果。

实现语法分析器的主要过程包括:- 初始化分析栈,将文法规则的开始符号入栈;- 从输入的程序代码中读取下一个终结符;- 如果分析栈的栈顶是非终结符,根据LL(1)分析表中对应的产生式编号,将产生式右部的符号依次入栈;- 如果分析栈的栈顶是终结符,并且与输入的终结符相同,则将该终结符出栈,并继续读取下一个终结符;- 重复上述过程,直到分析栈为空或者无法继续推导。

语法分析器设计实验报告

语法分析器设计实验报告

学号《编译原理》实验2:语法分析器设计学生姓名专业、班级指导教师赵璐成绩计算机与信息工程学院2018 年11 月27 日一、实验目的1.理解语法分析程序的功能。

2.熟悉语法分析程序的设计原理和构造方法。

3.掌握递归下降语法分析程序的构造方法。

4.设计一个递归下降的语法分析器,作为实验一构造的词法分析器的下一步编译工具,能语法分析前一步词法分析器输出的单词符号序列。

二、实验要求1.根据书P206给出的简单语言的语法规则,编写C或C++语言源程序,实现针对该简单语言的递归下降的语法分析器;2.独立做实验,输入、调试所编程序;3.实验结束后,根据实验报告模板编写实验报告。

三、实验内容和步骤用Visual C++作为实验开发环境,创建一个Win32 Console Application工程,工程名为你的学号,添加三个文件:(1)存储结构定义:以ParserDef.h和LexerDef.h为文件名;(2)基本操作的算法:以ParserAlgo.h和LexerAlgo.h为文件名;(3)调用基本操作的主程序:以ParserMain.cpp为文件名。

编写程序:(1)文件LexerDef.h和LexerAlgo.h为实验一的内容。

(2)文件ParserDef.h定义语法分析所需的全局变量等。

(3)文件ParserAlgo.h实现对语法规则中各语法成分的分析子算法。

(4)文件ParserMain.cpp实现针对P206简单语言语法规则的递归下降语法分析器。

源程序代码:=============================ParserDef.h================================ int kk;#define _KEY_WORD_END "waiting for your expanding"char * rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};char input[255];char token[255]="";int p_input;int p_token;char ch;============================ParserAlgo.h================================ char prog[80];int syn,p,m,n,sum=0;void scaner() {m=0;for(n=0; n<8; n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';syn=10;p=p-1; //回退一个字符for(n=0; n<6; n++) {if(strcmp(token,rwtab[n])==0) {syn=n+1;break;}}} else if(ch>='0' && ch<='9') {sum=0;while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=prog[p++];}p=p-1;syn=11;} else {switch(ch) {case '<':m=0;token[m++]=ch;ch=prog[p];if(ch=='>') {syn=21;token[m++]=ch;} else if(ch=='=') {syn=22;token[m++]=ch;} else {syn=20;p=p-1;}p=p+1;token[m]='\0';break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=24;token[m++]=ch;} else {syn=23;p=p-1;}break;case ':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=18;token[m++]=ch;} else {syn=17;p=p-1;}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}}============================ParserMain.cpp============================== #include<stdio.h>#include<stdlib.h>#include<string.h>#include"LexerDef.h"#include"ParserDef.h"#include"LexerAlgo.h"#include"ParserAlgo.h"void lrparser();void yucu();void statement();void expression();void term();void factor();void lrparser() {if (syn==1) { //beginscaner();yucu();if (syn==6) { //endscaner();if (syn==0 && kk==0) printf("success \n");} else {if(kk!=1) printf("error,lose 'end' ! \n");kk=1;}} else {printf("error,lose 'begin' ! \n");kk=1;}return;}void yucu() {statement();while(syn==26) {scaner();statement();}return;}void statement() {if (syn==10) { //为标识符scaner();if (syn==18) { //为:=scaner();expression();} else {printf("error!");kk=1;}} else {printf("error!");kk=1;}return;}void expression() {term();while(syn==13 || syn==14) {scaner();term();}return;}void term() {factor();while(syn==15 || syn==16) {scaner();factor();}return;}void factor() {if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号else if(syn==27) {scaner();expression();if(syn==28)scaner();else {printf(" ')' 错误\n");kk=1;}} else {printf("表达式错误\n");kk=1;}return;}void main() {p=0;printf("********************语法分析程序***************\n");printf("请输入源程序:\n");do {scanf("%c",&ch);prog[p++]=ch;} while(ch!='#');p=0;scaner();lrparser();printf("语法分析结束!\n");}四、解答下列问题(1)简述该语法分析器的算法思想。

语法分析器的设计

语法分析器的设计

语法分析器的设计1.设计原则在设计语法分析器时,应遵循以下原则:-维护清晰的分析策略:选择合适的文法类别,以便能够使用适当的分析策略,如自上而下分析、自下而上分析或混合分析等。

-使用适当的数据结构:选择合适的数据结构来表示词法单元流和语法树,以提高分析效率和易读性。

-错误处理机制:有效地处理语法错误,提供有用的错误信息以帮助开发人员进行调试和修复。

-可扩展性和可维护性:设计一个灵活的框架,使得分析器能够适应新的语言特性和文法规则,并便于维护和修改。

2.文法规则分析例如,下面是一个简单的四则运算表达式的文法规则:```<expression> ::= <term> '+' <expression><term> '-' <expression<term<term> ::= <factor> '*' <term><factor> '/' <term<factor<factor> ::= '(' <expression> ')'<number<number> ::= [0-9]+```在编写语法分析器时,需要将这些规则翻译为具体的代码逻辑。

3.自上而下分析自上而下分析是一种从文法规则的最上层开始,逐步展开产生式规则,并根据输入的词法单元流进行匹配的分析方法。

以下是一个简单的自上而下分析的伪代码示例:```function parseExpression(:term = parseTermif currentToken.type == '+':match('+')expression = parseExpressionreturn BinaryExpression('+', term, expression)else if currentToken.type == '-':match('-')expression = parseExpressionreturn BinaryExpression('-', term, expression) else:return termfunction parseTerm(:factor = parseFactorif currentToken.type == '*':match('*')term = parseTermreturn BinaryExpression('*', factor, term) else if currentToken.type == '/':match('/')term = parseTermreturn BinaryExpression('/', factor, term) else:return factorfunction parseFactor(:if currentToken.type == '(':match('(')expression = parseExpressionmatch(')')return expressionelse if currentToken.type == 'number':number = currentToken.valuematch('number')return NumberLiteral(number)else:error("Invalid factor")function match(expectedType):if currentToken.type == expectedType:currentToken = getNextTokenelse:error("Unexpected token: " + currentToken.type)```代码示例中的`currentToken`表示当前正在处理的词法单元,`getNextToken(`获取下一个词法单元。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理语法分析器的设计◆根据某一文法编制调试 LL ( 1 )分析程序,以便对任意输入的符号串进行分析。

◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。

◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

实验设计方案1、设计思想(1)、LL(1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。

LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。

LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。

需要预测分析器对所给句型进行识别。

即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。

LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。

若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。

(3)、语法分析程序构造LL(1)分析中X为符号栈栈顶元素,a为输入流当前字符,E为给定测试数据的开始符号,#为句子括号即输入串的括号。

分析表用一个二位数组M表示,数组元素M[A,a]中的下标A表示非终结符,a为终结符或句子括号‘#’,二维数组中存放的是一条关于A 的产生式,表明当非终结符A向下推导时,面临输入符a时,所采用的候选产生式,当元素内容无产生式时,则表明用A 的左部向下推导时出现了不该出现的符号,因此元素内容转向出错处理的信息。

LL(1)分析过程主要包括以下四个动作:替换:当X∈VN时选相应产生式的右部β去替换X。

此时X出栈,β逆序入栈。

匹配:当X∈VT时它与a进行匹配,其结果可能成功,也可能失败,如果成功则符号栈中将X退栈并将输入流指针向前移动一位,否则报错。

接受:当格局为(#,空#)时报告分析成功。

报错:出错后,停止分析。

并给出相应的错误提示信息。

2.程序流程图:3、实验程序(1)分析栈类:public class stack {private char s[];private int top;public stack() {s = new char[200];s[0] = '#';top = 0;}char getTop() {return s[top];}void push(String str) {for (int i = str.length() - 1; i >= 0; i--) {s[++top] = str.charAt(i);}}void clear() {top = 0;}char pop() {if (top != 0) {top--;}return s[top];}public String toString() {String tmp = "";for (int i = 0; i <= top; i++) {tmp += s[i];}return tmp;}}(2)语法分析器类:public class anlysis {//分析表private String tab[][] = { { "$", "+", "-", "*", "/", "(", ")", "i", "#" },{ "E", "$", "$", "$", "$", "TG", "$", "TG", "$" },{ "G", "+TG", "-TG", "$", "$", "$", "ε", "$", "ε" },{ "T", "$", "$", "$", "$", "FS", "$", "FS", "$" },{ "S", "ε", "ε", "*FS", "/FS", "$", "ε", "$", "ε" },{ "F", "$", "$", "$", "$", "(E)", "$", "i", "$" } };private String input; //input中存放输入的表达式private StringBuffer tempBuffer; //存放要输出的字符串private int ptr, row, col, step; //指针,预测表中的行,列,当前步骤private boolean symbol;private stack stack;public anlysis(){stack =new stack();tempBuffer = new StringBuffer();symbol=true;input="";row=1;ptr=0;step=1;}//////////////////////////////////methods./////////////////////////// //////public int column(char c) { //判断预测表中的列switch (c) {case'+':return 1;case'-':return 2;case'*':return 3;case'/':return 4;case'(':return 5;case')':return 6;case'i':return 7;case'#':return 8;default:return -1;}}public int line(char c) { //判定预测表中的行switch (c) {case'E':return 1;case'G':return 2;case'T':return 3;case'S':return 4;case'F':return 5;default:return -1;}}public void pri(String str) {tempBuffer.append(String.format("%-8d%-20s%-20s%-20s\r\n", step, stack.toString(), input.substring(ptr), str));step++;}public void analyse() {stack.push(tab[row][0]); //预测表中的第一个元素‘E’pri("初始化");String tmp;char ctmp; //栈顶元素while (!(input.charAt(ptr) == '#' && stack.getTop() == '#')) { ctmp = stack.getTop();if (input.charAt(ptr) == ctmp) { //与栈顶元素比较stack.pop();ptr++;pri("" + ctmp + "匹配");continue;}col = column(input.charAt(ptr));if (col == -1) {symbol = false;pri("未定义的字符");ptr++;continue;}row = line(ctmp);if (row == -1) {symbol = false;pri("出错");stack.pop();if (input.charAt(ptr) != '#') {ptr++;}continue;}tmp = tab[row][col];if (tmp.charAt(0) == '$') {symbol = false;pri("出错");stack.pop();if (input.charAt(ptr) != '#') {ptr++;}} else if (tmp.charAt(0) == 'ε') {stack.pop();pri("" + ctmp + "->" + 'ε');} else {stack.pop();stack.push(tmp);pri("" + ctmp + "->" + tmp);}}}public String work(String ts) {input = ts;input = input.trim()+ '#';symbol = true;stack.clear();tempBuffer.append("\r\n步骤分析栈剩余输入栈所用产生式\r\n");analyse();if (symbol) {tempBuffer.append("\r是正确的符号串\r");return tempBuffer.toString();} else {tempBuffer.append("\r不是正确的符号串\r");return tempBuffer.toString();}}////////////////////////////////////gets andsets////////////////////////////////public StringBuffer getTempBuffer() {return tempBuffer;}public void setTempBuffer(StringBuffer tempBuffer) { this.tempBuffer = tempBuffer;}public stack getStack() {return stack;}public void setStack(stack stack) {this.stack = stack;}public String[][] getTab() {return tab;}public void setTab(String[][] tab) {this.tab = tab;}public String getInput() {return input;}public void setInput(String ns) {this.input = ns;}public int getPtr() {return ptr;}public void setPtr(int ptr) {this.ptr = ptr;}public int getRow() {return row;}public void setRow(int row) {this.row = row;}public int getCol() {return col;}public void setCol(int col) {this.col = col;}public int getStep() {return step;}public void setStep(int step) {this.step = step;}public boolean isBoo() {return symbol;}public void setBoo(boolean boo) {this.symbol = boo;}}(3)WINDOW窗体类:import java.awt.BorderLayout;import java.awt.GridLayout;import java.awt.Panel;import javax.swing.JFrame;import javax.swing.JScrollPane;public class gui extends javax.swing.JFrame {/** Creates new form gui */private javax.swing.JButton jButton1;private javax.swing.JLabel jLabel1;private javax.swing.JLabel jLabel2;private javax.swing.JTextArea jTextArea1;private javax.swing.JTextField jTextField1;private Panel p1=new Panel();private Panel p2=new Panel();public gui() {initComponents();}private void initComponents() {jLabel1 = new javax.swing.JLabel();jTextField1 = new javax.swing.JTextField();jLabel2 = new javax.swing.JLabel();jTextArea1 = new javax.swing.JTextArea(20,30);jButton1 = new javax.swing.JButton();setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOS E);jLabel1.setText("本程序只能对由'+','-','*','/','(',')','i'构成的以'#'结尾的字符串进行分析。

相关文档
最新文档