编译原理 LR(0)分析过程的实现
《编译原理》中LR(0)语法分析动态演示系统分析与设计
《编译原理》中LR(0)语法分析动态演示系统分析与设计一、引言随着计算机科学领域的不断发展,编译原理作为计算机科学的核心课程之一,对于理解编程语言和编译器的原理和技术具有重要意义。
LR(0)语法分析作为编译器中的重要组成部分,在编译原理课程中具有重要的地位。
为了更好地理解与掌握LR(0)语法分析,本文将课程中的相关理论与实践相结合,提出了一个LR(0)语法分析动态演示系统的设计与分析。
二、LR(0)语法分析概述在编译器的构建中,语法分析是非常重要的一环。
而LR(0)语法分析是一种常用的语法分析方法之一。
LR(0)语法分析使用的是LR(0)自动机进行分析,它是一种自底向上的语法分析方法,它的优势在于可以处理大部分的上下文无关文法(Context-Free Grammar, CFG),并且可以准确地进行语法分析。
LR(0)语法分析是通过构建状态机的方式,根据文法产生式中的右部项目来进行状态转换并最终得到文法的推导序列。
为了更好地理解LR(0)语法分析的原理与过程,我们需要深入学习LR(0)自动机的构建过程、状态转换的规则以及分析过程的具体步骤。
仅仅通过理论学习,学生们往往难以深刻理解LR(0)语法分析的工作原理与流程。
我们需要设计一个能够直观演示LR(0)语法分析过程的系统,通过动态的展示来帮助学生更好地理解LR(0)语法分析的过程和原理。
三、LR(0)语法分析动态演示系统的需求分析为了实现LR(0)语法分析动态演示系统,首先需要进行系统需求分析,明确系统的功能需要和用户需求。
根据LR(0)语法分析的原理与过程,系统的主要功能需求包括:1. 文法输入:能够接受用户输入的文法表达式,包括非终结符、终结符及产生式。
2. LR(0)自动机构建:根据用户输入的文法表达式自动生成LR(0)自动机,并进行展示。
3. 状态转换展示:根据LR(0)自动机中的状态转换规则,动态展示状态之间的转换过程及转换规则。
4. 分析过程展示:根据LR(0)自动机和输入的句子,展示分析过程中状态的变化和产生式的规约过程。
编译原理词法分析器-ll1-lr0-python实现代码
编译原理词法分析器-ll1-lr0-python实现代码计算机科学与通信工程学院编译原理实验报告题目: 1.词法分析器2. LL(1)分析器3. LR(0)分析器班级:姓名:学号:指导老师:2017年月目录一、实验题目 (1)二、实验目的和要求 (1)三、代码实现 (2)四、总结 (25)一、实验题目1.词法分析器分析一段程序代码,将代码中的单词符号分解出来,并对其进行检查,输出token表和error表2.LL(1)文法分析器分析给定文法。
求出文法的FIRST集,FOLLOW集,并构建分析表,对给定输入串进行分析。
3.LR(0)文法分析器分析给定文法。
用Ꜫ_CLOSURE方法构造文法的LR(0)项目集规范族,根据状态转换函数GO构造出文法的DFA,并转换为分析表,对给定输入串进行分析。
二、实验目的和要求1.学会词法分析器的实现思路。
2.学会求解FIRST集, FOLLOW集,构造LL(1)分析表。
3.学会Ꜫ_CLOSURE方法,状态转换函数GO, 构造LR(0)分析表。
三、代码实现1.词法分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i代码:KEYWORD_LIST = ['while', 'if', 'else', 'switch', 'case']SEPARATOR_LIST = [';', ':', ',', '(', ')', '[', ']', '{', '}']OPERATOR_LIST1 = ['+', '-', '*']OPERATOR_LIST2 = ['<=', '<', '==', '=', '>', '>=']CATEGORY_DICT = {# KEYWORD"while": {"while": ""},"if": {"if": ""},"else": {"else": ""},"switch": {"switch": ""},"case": {"case": ""},# OPERATOR"+": {"+": ""},"-": {"-": ""},"*": {"*": ""},"<=": {"relop": "LE"},"<": {"relop": "LT"},">=": {"relop": "GE"},">": {"relop": "GT"},"==": {"relop": "EQ"},"=": {"=": ""},# SEPARATOR";": {";": ""},":": {":": ""},",": {",": ""},"(": {"(": ""},")": {")": ""},"[": {"]": ""},"]": {"]": ""},"{": {"{": ""},"}": {"}": ""},}CONSTANTTABLE = []TOKENTABLE = []OPERATORTABLE = []KEYWORDTABLE = []SEPARATORTABLE = []UNDEFINEDTABLE = []# READ FILEdef read_file(path, method):temp_str = ""try:file = open(path, method)for line in file:line = line.replace('\n', " ") temp_str += linetemp_str = str(temp_str)except IOError as e:print(e)exit()finally:file.close()return temp_str.strip() + " "# GETBEdef getbe():global tokengetchar()token = ""return# GETCHARdef getchar():global characterglobal locationwhile all_string[location] == " ":location = location + 1character = all_string[location]return character# LINK TOKENdef concatenation():global tokenglobal charactertoken = token + character# IS NUMBERdef digit():if '0' <= character <= '9':return Truereturn False# IS ALPHABETdef letter():if 'A' <= character <= 'Z' or 'a' <= character <= 'z': return Truereturn False# IS IDENTIFIERdef reserve():if token in KEYWORD_LIST:return CATEGORY_DICT[token]else:return 0# RETRACTdef retract():global locationglobal character# location = location - 1character = ""return# MAIN FUNCTIONdef main():global tokenglobal characters = getchar()getbe()if 'a' <= s <= 'z' or 'A' <= s <= 'Z':while letter() or digit():concatenation()location = location + 1character = all_string[location]retract()c = reserve()if c == 0:TOKENTABLE.append(token)print("这是标识符:{'", token, "':'", TOKENTABLE.index(token), "'}") else:KEYWORDTABLE.append(token)print("这是保留字:", CATEGORY_DICT[token])elif '0' <= s <= '9':while digit():concatenation()location = location + 1character = all_string[location]retract()CONSTANTTABLE.append(token)print("这是常数:{'", token, "':'", CONSTANTTABLE.index(token), "'}") elif s in OPERATOR_LIST1:location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in OPERATOR_LIST2:location = location + 1character = all_string[location]if character == '=':OPERATORTABLE.append(s + character)print("这是双操作符:", CATEGORY_DICT[s + character])else:retract()location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in SEPARATOR_LIST:location = location + 1SEPARATORTABLE.append(s)print("这是分隔符:", CATEGORY_DICT[s])else:UNDEFINEDTABLE.append(s)print("error:undefined identity :'", s, "'")if __name__ == '__main__':character = ""token = ""all_string = read_file("program.txt", "r")location = 0while location + 1 < len(all_string):main()print('KEYWORDTABLE:', KEYWORDTABLE)print('TOKENTABLE:', TOKENTABLE)print('CONSTANTTABLE:', CONSTANTTABLE)print('OPERATORTABLE:', OPERATORTABLE)print('SEPARATORTABLE:', SEPARATORTABLE)运行结果:2.LL(1)分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i输入串:i+i*i代码:NonTermSet = set() # 非终结符集合TermSet = set() # 终结符集合First = {} # First集Follow = {} # Follow集GramaDict = {} # 处理过的产生式Code = [] # 读入的产生式AnalysisList = {} # 分析表StartSym = "" # 开始符号EndSym = '#' # 结束符号为“#“Epsilon = "~" # 由于没有epsilon符号用“~”代替# 构造First集def getFirst():global NonTermSet, TermSet, First, Follow, FirstAfor X in NonTermSet:First[X] = set() # 初始化非终结符First集为空for X in TermSet:First[X] = set(X) # 初始化终结符First集为自己Change = Truewhile Change: # 当First集没有更新则算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:k = 0Continue = Truewhile Continue and k < len(Y):if not First[Y[k]] - set(Epsilon) <= First[X]: # 没有一样的就添加,并且改变标志if Epsilon not in First[Y[k]] and Y[k] in NonTermSet and k > 0: # Y1到Yi候选式都有~存在Continue = Falseelse:First[X] |= First[Y[k]] - set(Epsilon)Change = Trueif Epsilon not in First[Y[k]]:Continue = Falsek += 1if Continue: # X->~或者Y1到Yk均有~产生式First[X] |= set(Epsilon)# FirstA[Y] |= set(Epsilon)# 构造Follow集def getFollow():global NonTermSet, TermSet, First, Follow, StartSymfor A in NonTermSet:Follow[A] = set()Follow[StartSym].add(EndSym) # 将结束符号加入Follow[开始符号]中Change = Truewhile Change: # 当Follow集没有更新算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:for i in range(len(Y)):if Y[i] in TermSet:continueFlag = Truefor j in range(i + 1, len(Y)): # continueif not First[Y[j]] - set(Epsilon) <= Follow[Y[i]]:Follow[Y[i]] |= First[Y[j]] - set(Epsilon) # 步骤2 FIRST(β)/~ 加入到FOLLOW(B)中。
编译原理LR分析(主要是LR(0)分析)
编译原理LR分析(主要是LR(0)分析)⼀、LR分析的基本原理1、LR分析的基本思想LR⽅法的基本思想就是,在规范归约的过程中,⼀⽅⾯要记住已移进和归约出的整个字符串,也就是说要记住历史;⼀⽅⾯能够根据所⽤的产⽣式的推测未来可能碰到的输⼊符号,也就是说能够对未来进⾏展望。
这样,当⼀串貌似句柄的字符串出现在分析栈的顶部时,我们希望能够根据历史和展望以及现实的输⼊符号这三部分的材料,决定出现在栈顶的这⼀串符号是否就是我们要找的句柄。
2、LR分析器的构成采⽤下推⾃动机这种数据模型。
包括以下⼏个部分:1.输⼊带2.分析栈:包括状态栈和⽂法符号栈两部分。
(s0,#)为分析开始前预先放在栈⾥的初始状态和句⼦括号。
3.LR 分析表:包括动作表和状态转移表两张表。
3、LR分析表是LR分析器的核⼼部分⼀张LR分析表包括两部分:动作表(ACTION)和状态转换表(GOTO)。
它们都是⼆维数组。
ACTION[s,a]规定了当状态s⾯临输⼊符号a时应采取什么动作(移进、归约、接受和报错),⽽GOTO[s,X]规定了当状态s⾯对⽂法符号X(终结符或⾮终结符)时的下⼀状态是什么。
显然,GOTO[s,X]定义了⼀个以⽂法符号为字母表的DFA。
不同的 LR 分析法构造LR分析表的⽅法都不同,由此产⽣了不同的LR分析法。
4、LR分析算法置ip指向输⼊串w的第⼀个符号 令Si为栈顶状态 a是ip指向的符号(当前输⼊符号) BEGIN(重复开始) IF ACTION[Si,a]=Sj THENBEGINPUSH j,a (进栈) ip前进(指向下⼀输⼊符号) END ELSEIF ACTION[Si,a]=rj(若第j条产⽣式为A→β) THEN BEGIN pop|β| 项 若当前栈顶状态为Sk pushGOTO[Sk,A] 和A(进栈) END ELSEIF ACTION[Si,a]=acc THEN return (成功) ELSE error END. (重复结束)⼆、LR(0)分析器1、可归前缀与规范句型的活前缀⽂法G[S]:(1) S → aAcBe[1](2) A → b[2](3) A → Ab[3](4) B → d[4]S ÞaAcBe[1]ÞaAcd[4]e[1]ÞaAb[3]cd[4]e[1]Þab[2]b[3]cd[4]e[1]每次归约句型的前部分依次为:ab[2]aAb[3]aAcd[4]aAcBe[1]规范句型的这种前部分符号串称为可归前缀我们把形成可归前缀之前包括可归前缀在内的所有规范句型的前缀都称为活前缀(活前缀就是可归前缀的前缀)如下:e,a,abe ,a,aA,aAbe ,a,aA,aAc,aAcde ,a,aA,aAc,aAcB,aAcBe三、LR分析(⼀)LR分析构造识别活前缀的有穷⾃动机项⽬(item):在每个产⽣式的右部适当位置添加⼀个圆点构成项⽬。
编译原理实验自动生成LR分析表
编译原理实验自动生成LR分析表2016.12.14自动生成LR(0)分析表目录一、实验名称 (2)二、实验目的 (2)三、实验原理 (2)1、闭包closure(I) (2)2、转换函数GO(I,X) (2)3、ACTION子表和GOTO子表的构造 (2)四、实验思路 (3)1、输入 (3)2、建立项目 (3)3、closure算法 (3)4、转向函数GO(I,X)的算法 (3)5、建立状态及对应的项目集 (3)6、ACTION子表的构造 (4)7、GOTO子表的构造 (4)五、实验小结 (4)六、附件 (5)1、源代码 (5)2、运行结果截图 (9)一、实验名称自动生成LR(0)分析表二、实验目的1、实现计算闭包函数CLOSURE的算法。
2、实现转向函数GO(I,X)的算法。
3、实现ACTION子表和GOTO子表的构造算法。
4、输入任意的压缩了的上下文无关文法,输出相应的LR(0)分析表(以表格形式输出)。
三、实验原理1、闭包closure(I)若文法G已拓广为G’,而S为文法G的开始符号,拓广后增加产生式S’->S。
如果I是文法G’的一个项目集,定义和构造I的闭包closure(I)如下:a.I的项目在closure(I)中。
b.若A->α?Bβ属于closure(I),则每一形如B->?γ的项目也属于closure(I)。
c.重复b直到不出现新的项目为止。
即closure(I)不再扩大。
2、转换函数GO(I,X)GO(I,X)=closure(J)其中:I为包含某一项目集的状态。
X为一文法符号,X∈Vn∪VtJ={任何形如A->α?Xβ的项目|A->αX?β属于I}3、ACTION子表和GOTO子表的构造a.若项目A→α.aβ属于Ik且GO (Ik, a)= Ij, a为终结符,则置ACTION[k, a]为“把状态j和符号a移进栈”,简记为“sj”;b.若项目A→α.属于Ik,那么,对任何终结符a,置ACTION[k,a]为“用产生式A→α进行规约”,简记为“rj”;其中,假定A→α为文法G'的第j个产生式c.若项目S'→S.属于Ik, 则置ACTION[k, #]为“接受”,简记为“acc”;d.若GO (Ik, A)= Ij, A为非终结符,则置GOTO[k, A]=j;e.分析表中凡不能用上述1至4填入信息的空白格均置上“出错标志”。
《编译原理》中LR(0)语法分析动态演示系统分析与设计
《编译原理》中LR(0)语法分析动态演示系统分析与设计一、引言编译原理是计算机科学与技术中的重要课程,它研究的是如何将高级程序语言翻译成机器语言的技术和方法。
在编译原理中,LR(0)语法分析是一个重要的内容,它是通过自底向上的方式进行语法分析的一种方法。
在学习编译原理的过程中,学生往往会遇到对LR(0)语法分析的理解困难,因为它涉及到许多抽象的概念和算法。
为了更好地帮助学生理解和掌握LR(0)语法分析,本文针对LR(0)语法分析动态演示系统进行了分析与设计,旨在通过动态演示的方式帮助学生更直观、深入地理解LR(0)语法分析的原理和过程。
二、LR(0)语法分析方法简介LR(0)语法分析是一种自底向上的语法分析方法,它能够对任意上下文无关文法(CFG)进行语法分析。
LR(0)语法分析的基本思想是通过分析输入串中的符号和栈中的符号,逐步地将输入串转换为目标符号串的过程。
在LR(0)语法分析中,使用LR(0)自动机来表示语法分析过程,并通过自动机的状态转换来完成对输入串的分析。
LR(0)语法分析包括了自动机的构建、状态的扩展和分析过程三个基本步骤,每个步骤都涉及到大量的状态转换和符号匹配。
三、LR(0)语法分析动态演示系统分析1. 功能需求分析为了帮助学生更直观、深入地理解LR(0)语法分析的原理和过程,需要实现一个动态演示系统,该系统应该具备以下基本功能:(1)自动机的构建:实现LR(0)自动机的构建过程,包括状态的生成、状态的扩展和状态转换规则的确定。
(2)状态的扩展:实现LR(0)自动机中状态的扩展过程,包括向状态图中添加新的状态和确定转移规则。
(3)分析过程演示:实现LR(0)语法分析的过程演示,包括输入串的处理和状态转换规则的应用。
2. 界面设计分析3. 技术实现分析动态演示系统的技术实现应该能够满足LR(0)语法分析的模拟和演示需求,具体应该采用以下技术实现方案:(1)使用HTML、CSS和JavaScript实现界面设计,实现LR(0)自动机状态图的展示和交互功能。
实验三编译原理综合实验报告——(LR(0)语法分析的实现)
m_pTree->SetControlInfo(IDC_TREE1, RESIZE_BOTH);
m_pTree->SetControlInfo(IDOK, ANCHORE_BOTTOM | ANCHORE_RIGHT);
void CAnalyzeDlg::OnOK()
{
// TODO: Add extra validation here
//CDialog::OnOK();
}
void CAnalyzeDlg::OnCancel()
{
// TODO: Add extra cleanup here
六、实验原理、数据(程序)记录
(一)实验原理:
利用LR(k)类分析算法的四个步骤,分别实现"移进"、"归约"、"成功"、"报错"的分析能力。同时采用相应的数据结构实现分析表的描述。
(二)程序框架:
#include "stdafx.h"
#include "GoData.h"
GoData::GoData()
assert(j != -1);
out.WriteString(GetStepInfo(iStep, Status, Symbol, m_input.Right(m_input.GetLength() - iPos), ToDo, j));
for(i = 0; i < m_g.GetPrecept(ToDo.two).GetRight().length(); i++)
(完整word版)编译原理报告二LR分析器
LR分析器一、目的和要求通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,并至少完成两个题目。
2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
⑴实验前的准备按实验的目的和要求,编写语法分析程序,同时考虑相应的数据结构。
⑵调试调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。
⑶输出对于所输入的算术表达式,不论对错,都应有明确的信息告诉外界。
⑷扩充有余力的同学,可适当扩大分析对象。
譬如:①算术表达式中变量名可以是一般标识符,还可含一般常数、数组元素、函数调用等等。
②除算术表达式外,还可扩充分析布尔、字符、位等不同类型的各种表达式。
③加强语法检查,尽量多和确切地指出各种错误。
⑸编写上机实习报告。
二、背景知识※自下而上分析技术-LR(K)方法LR(K)方法是一种自下而上的语法分析方法,是当前最广义的无回溯的“移进- 归约”方法。
它根据栈中的符号串和向前查看的k(k³0)个输入符号,就能唯一确定分析器的动作是移进还是归约,以及用哪个产生式进行归约。
优点:文法适用范围广;识别效率高;查错能力强;可自动构造。
逻辑组成:总控程序+LR分析表LR分析器的结构:一个LR分析器实际是一个带先进后出存储器(栈)的确定下推自动机,它由一个输入串、一个下推栈和一个带有分析表的总控程序组成。
栈中存放着由“历史”和“展望”材料抽象而来的各种“状态”。
任何时候,栈顶的状态都代表了整个的历史和已推测出的展望。
为了有助于明确归约手续,我们把已归约出的文法符号串也同时放进栈里。
LR分析器的每一动作都由栈顶状态和当前输入符号所唯一确定。
LR分析器模型图分析器的任何一次移动都是根据栈顶状态S m和当前输入符号a i,去查看ACTION表并执行ACTION (S m,a i)规定的动作,直至分析成功或失败。
编译原理LR(0)分析器(C语言)
LR0分析法编译原理实验
代码清单:#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cctype>#include <vector>#include <string>#include <queue>#include <map>#include <sstream>#define MAX 507#define DEBUGusing namespace std;class WF{public:string left,right;int back;int id;WF ( char s1[] , char s2[] , int x , int y ){left = s1;right = s2;back = x;id = y;}WF ( const string& s1 , const string& s2 , int x , int y ){left = s1;right = s2;back = x;id = y;}bool operator < ( const WF& a ) const{if ( left == a.left )return right < a.right;return left < a.left;}bool operator == ( const WF& a ) const{return ( left == a.left )&& ( right == a.right );}void print ( ){printf ( "%s->%s\n" , left.c_str() , right.c_str() );}};class Closure{public:vector<WF> element;void print ( string str ){printf ( "%-15s%-15s\n" , "" , str.c_str());for ( int i = 0 ; i < element.size() ; i++ )element[i].print();}bool operator == ( const Closure& a ) const{if ( a.element.size() != element.size() ) return false;for ( int i = 0 ; i < a.element.size() ; i++ )if ( element[i] == a.element[i] ) continue;else return false;return true;}};struct Content{int type;int num;string out;Content(){ type = -1; }Content ( int a , int b ):type(a),num(b){}};vector<WF> wf;map<string,vector<int> > dic;string start = "S";vector<Closure> collection;vector<WF> items;char CH = '$';int go[MAX][MAX];int to[MAX];vector<char> V;bool used[MAX];Content action[MAX][MAX];int Goto[MAX][MAX];void make_item ( ){memset ( to , -1 , sizeof ( -1 ) );for ( int i = 0 ; i < wf.size() ; i++ )for ( int j = 0 ; j <= wf[i].right.length() ; j++ ){string temp = wf[i].right;temp.insert( temp.begin()+j , CH );dic[wf[i].left].push_back ( items.size() );if ( j )to[items.size()-1] = items.size();items.push_back ( WF ( wf[i].left , temp , i , items.size()) );}#ifdef DEBUGputs("-------------------------项目表-------------------------");for ( int i = 0 ; i < items.size() ; i++ ) printf ( "%s->%s\n" , items[i].left.c_str() , items[i].right.c_str() );puts("--------------------------------------------------------");#endif}void make_set ( ) {bool has[MAX];for ( int i = 0 ; i < items.size() ; i++ ) if ( items[i].left[0] == 'S' && items[i].right[0] == CH ){Closure temp;string& str = items[i].right;vector<WF>& element = temp.element;element.push_back( items[i] );int x = 0;for ( x = 0 ; x < str.length() ; x++ )if ( str[x] == CH )break;memset ( has , 0 , sizeof ( has ) );has[i] = 1;if ( x != str.length()-1 ){queue<string> q;q.push( str.substr(x+1,1) );while ( !q.empty() ){string u = q.front();q.pop();vector<int>& id = dic[u];for( int j = 0 ; j < id.size() ; j++ ){int tx = id[j];if( items[tx].right[0] == CH ){if( has[tx] ) continue;has[tx] = 1;if( isupper(items[tx].right[1] ) )q.push ( items[tx].right.substr(1,1));element.push_back ( items[tx] );}}}}collection.push_back( temp );}for ( int i = 0 ; i < collection.size() ; i++ ){map<int,Closure> temp;for ( int j = 0 ; j < collection[i].element.size() ; j++ ){string str = collection[i].element[j].right;int x = 0;for ( ; x < str.length() ; x++ )if ( str[x] == CH ) break;if ( x == str.length()-1 )continue;int y = str[x+1];int ii;str.erase ( str.begin()+x);str.insert ( str.begin()+x+1 , CH );WF cmp = WF ( collection[i].element[j].left , str , -1 , -1 );for ( int k = 0 ; k< items.size() ; k++ )if ( items[k] == cmp ){ii = k;break;}memset ( has , 0 , sizeof ( has ) );vector<WF>& element = temp[y].element;element.push_back( items[ii] );has[ii] = 1;x++;if ( x != str.length()-1 ){queue<string> q;q.push( str.substr(x+1,1) );while ( !q.empty() ){string u = q.front();q.pop();vector<int>& id = dic[u];for( int j = 0 ; j < id.size() ; j++ ){int tx = id[j];if( items[tx].right[0] == CH ){if( has[tx] ) continue;has[tx] = 1;if( isupper(items[tx].right[1] ) )q.push ( items[tx].right.substr(1,1));element.push_back ( items[tx] );}}}}}map<int,Closure>::iterator it = temp.begin();for ( ; it != temp.end() ; it++ )collection.push_back ( it->second );for ( int i = 0 ; i < collection.size() ; i++ )sort( collection[i].element.begin() , collection[i].element.end() );for ( int i = 0 ; i < collection.size() ; i++ )for ( int j = i+1 ; j < collection.size() ; j++ )if ( collection[i] == collection[j] )collection.erase ( collection.begin()+j );}#ifdef DEBUGputs("-------------CLOSURE---------------------");stringstream sin;for ( int i = 0 ; i < collection.size() ; i++ ){sin.clear();string out;sin <<"closure-I" << i;sin >> out;collection[i].print ( out );}puts("");#endif}void make_V ( ){memset ( used , 0 , sizeof ( used ) );for ( int i = 0 ; i < wf.size() ; i++ ){string& str = wf[i].left;for ( int j = 0 ; j < str.length() ; j++ ){if ( used[str[j]] ) continue;used[str[j]] = 1;V.push_back ( str[j] );}string& str1 = wf[i].right;for ( int j = 0 ; j < str1.length() ; j++ ){if ( used[str1[j]] ) continue;used[str1[j]] = 1;V.push_back ( str1[j] );}}sort ( V.begin() , V.end() );V.push_back ( '#' );}void make_cmp ( vector<WF>& cmp1 , int i , char ch ){for ( int j = 0 ; j < collection[i].element.size() ; j++ ){string str = collection[i].element[j].right;int k;for ( k = 0 ; k < str.length() ; k++ )if ( str[k] == CH )break;if ( k != str.length() - 1 && str[k+1] == ch ){str.erase ( str.begin()+k);str.insert ( str.begin()+k+1 , CH );cmp1.push_back ( WF ( collection[i].element[j].left , str , -1 , -1 ) );}}sort ( cmp1.begin() , cmp1.end() ); }void make_go ( ){memset ( go , -1 , sizeof ( go ) );int m = collection.size();for ( int t = 0 ; t < V.size() ; t++ ){char ch = V[t];for ( int i = 0 ; i < m ; i++ ){vector<WF> cmp1;make_cmp ( cmp1 , i , ch );cout << cmp1.size() << endl;if ( cmp1.size() == 0 ) continue;for ( int j = 0 ; j < m ; j++ ){vector<WF> cmp2;for ( int k = 0 ; k < collection[j].element.size() ; k++ ){string& str = collection[j].element[k].right;int x;for ( x = 0 ; x < str.length() ; x++ )if ( str[x] == CH )break;if ( x && str[x-1] == ch )cmp2.push_back( WF( collection[j].element[k].left , str , -1 , -1 ) );}sort ( cmp2.begin() , cmp2.end() );cout << cmp2.size() << endl;bool flag = true;if ( cmp2.size() != cmp1.size() ) continue;cout << cmp1.size() << endl;for ( int k = 0 ; k < cmp1.size() ; k++ )if ( cmp1[k] == cmp2[k] ) continue;else flag = false;cout << "out " << endl;if ( flag )go[i][ch] = j;}}}#ifdef DEBUGputs("---------------EDGE----------------------");stringstream sin;string out;for ( int i = 0 ; i < m ; i++ )for ( int j = 0 ; j < m ; j++ )for ( int k = 0 ; k < MAX ; k++ )if ( go[i][k] == j ){sin.clear();sin << "I" << i << "--" <<(char)(k)<<"--I"<<j;sin >> out;printf ( "%s\n" , out.c_str() );}#endif}void make_table ( ){memset ( Goto , -1 , sizeof ( Goto ) );for( int i = 0 ; i < collection.size() ; i++ )for ( int j = 0 ; j < V.size() ; j++ ){char ch = V[j];int x = go[i][ch];if ( x == -1 ) continue;if ( !isupper(ch) )action[i][ch] = Content ( 0 , x );elseGoto[i][ch] = x;}for ( int i = 0 ; i < collection.size() ; i++ )for ( int j = 0 ; j < collection[i].element.size() ; j++ ){WF& tt = collection[i].element[j];if( tt.right[tt.right.length()-1] == CH ){if ( tt.left[0] == 'S' )action[i]['#'] = Content ( 2 , -1 );elsefor ( int k = 0 ; k < V.size() ; k++ ){int y = V[k];action[i][y] = Content ( 1, tt.back );}}}#ifdef DEBUGputs( "------------------------------------------LR(0)分析表--------------------------------------------------------" );printf ( "%10s%5c%5s" , "|" , V[0] , "|");for ( int i = 1 ; i < V.size() ; i++ )printf ( "%5c%5s" , V[i] , "|" );puts ("");for ( int i = 0 ; i < (V.size()+1)*10 ; i++ )printf ( "-" );puts("");stringstream sin;for ( int i = 0 ; i < collection.size() ; i++ ){printf ( "%5d%5s" , i , "|" );for ( int j = 0 ; j < V.size() ; j++ ){char ch = V[j];if ( isupper(ch) ){if ( Goto[i][ch] == -1 )printf ( "%10s" , "|" );elseprintf ( "%5d%5s" , Goto[i][ch] , "|" );}else{sin.clear();if ( action[i][ch].type == -1 )printf ( "%10s" , "|" );else{Content& temp = action[i][ch];if ( temp.type == 0 )sin << "S";if ( temp.type == 1 )sin << "R";if ( temp.type == 2 )sin << "acc";if ( temp.num != -1 )sin << temp.num;sin >> temp.out;printf ( "%7s%3s" , temp.out.c_str() , "|" );}}}puts ("");}for ( int i = 0 ; i < (V.size()+1)*10 ; i++ )printf ( "-" );puts("");#endif}void print ( string s1 , string s2 , string s3 , string s4 , string s5 , string s6 , string s7 ){printf( "%-15s|%-15s%-15s%-20s|%-15s%-15s%-15 s\n" , s1.c_str() , s2.c_str() , s3.c_str() ,s4.c_str(),s5.c_str(),s6.c_str() , s7.c_str() );}string get_steps ( int x ){stringstream sin;sin << x;string ret;sin >> ret;return ret;}template<class T>string get_stk ( vector<T> stk ){stringstream sin;for ( int i = 0 ; i < stk.size() ; i++ )sin << stk[i];string ret;sin >> ret;return ret;}string get_shift ( WF& temp ){stringstream sin;sin << "reduce(" << temp.left << "->" << temp.right <<")";string out;sin >> out;return out;}void analyse ( string src ){print( "steps","op-stack" ,"input","operation","s tate-stack" , "ACTION" , "GOTO" );vector<char> op_stack;vector<int> st_stack;src+= "#";op_stack.push_back ( '#' );st_stack.push_back ( 0 );int steps= 1;for ( int i = 0 ; i < src.length() ; i++ ){char u = src[i];int top = st_stack[st_stack.size()-1];Content& act = action[top][u];if ( act.type == 0 ){print ( get_steps ( steps++ ) , get_stk ( op_stack ) , src.substr(i), "shift", get_stk( st_stack ) , act.out , "" );op_stack.push_back ( u );st_stack.push_back( act.num );}else if ( act.type == 1 ){WF& tt = wf[act.num];int y = st_stack[st_stack.size()-tt.right.length()-1];int x = Goto[y][tt.left[0]];print ( get_steps ( steps++ ) , get_stk ( op_stack ) , src.substr(i) , get_shift(tt) ,get_stk( st_stack),act.out,g et_steps(x));for ( int j = 0 ; j < tt.right.length() ; j++ ){st_stack.pop_back();op_stack.pop_back();}op_stack.push_back( tt.left[0] );st_stack.push_back ( x );i--;}else if ( act.type == 2 ){print ( get_steps( steps++ ), get_stk( op_stack ) , src.substr(i) , "Accept" , get_stk(st_stack) , act.out ,"" );}else continue;}}int main ( ){int n;char s[MAX];while ( ~scanf ( "%d" , &n ) ){for ( int i = 0 ; i < n ; i++ ){scanf ( "%s" , s );int len = strlen(s),j;for ( j = 0 ; j < len ; j++ )if ( s[j] == '-' ) break;s[j] = 0;wf.push_back ( WF ( s , s+j+2 ,-1 , -1 ) );#ifdef DEBUGwf[wf.size()-1].print();#endif}make_item();make_set();make_V();make_go();make_table();analyse ( "abbcde" );}}运行结果:。
编译原理词法分析器,ll1,lr0,python实现代码
计算机科学与通信工程学院编译原理实验报告题目: 1.词法分析器2. LL(1)分析器3. LR(0)分析器班级::学号:指导老师:2017年月目录一、实验题目 (1)二、实验目的和要求 (1)三、代码实现 (2)四、总结 (27)一、实验题目1.词法分析器分析一段程序代码,将代码中的单词符号分解出来,并对其进行检查,输出token表和error表2.LL(1)文法分析器分析给定文法。
求出文法的FIRST集,FOLLOW集,并构建分析表,对给定输入串进行分析。
3.LR(0)文法分析器分析给定文法。
用Ꜫ_CLOSURE方法构造文法的LR(0)项目集规族,根据状态转换函数GO构造出文法的DFA,并转换为分析表,对给定输入串进行分析。
二、实验目的和要求1.学会词法分析器的实现思路。
2.学会求解FIRST集, FOLLOW集,构造LL(1)分析表。
3.学会Ꜫ_CLOSURE方法,状态转换函数GO, 构造LR(0)分析表。
三、代码实现1.词法分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i代码:KEYWORD_LIST = ['while', 'if', 'else', 'switch', 'case']SEPARATOR_LIST = [';', ':', ',', '(', ')', '[', ']', '{', '}'] OPERATOR_LIST1 = ['+', '-', '*']OPERATOR_LIST2 = ['<=', '<', '==', '=', '>', '>=']CATEGORY_DICT = {# KEYWORD"while": {"while": ""},"if": {"if": ""},"else": {"else": ""},"switch": {"switch": ""},"case": {"case": ""},# OPERATOR"+": {"+": ""},"-": {"-": ""},"*": {"*": ""},"<=": {"relop": "LE"},"<": {"relop": "LT"},">=": {"relop": "GE"},">": {"relop": "GT"},"==": {"relop": "EQ"},"=": {"=": ""},# SEPARATOR";": {";": ""},":": {":": ""},",": {",": ""},"(": {"(": ""},")": {")": ""},"[": {"]": ""},"]": {"]": ""},"{": {"{": ""},"}": {"}": ""},}CONSTANTTABLE = []TOKENTABLE = []OPERATORTABLE = []KEYWORDTABLE = []SEPARATORTABLE = []UNDEFINEDTABLE = []# READ FILEdef read_file(path, method):temp_str = ""try:file = open(path, method)for line in file:line = line.replace('\n', " ") temp_str += linetemp_str = str(temp_str)except IOError as e:print(e)exit()finally:file.close()return temp_str.strip() + " "# GETBEdef getbe():global tokengetchar()token = ""return# GETCHARdef getchar():global characterglobal locationwhile all_string[location] == " ":location = location + 1character = all_string[location]return character# LINK TOKENdef concatenation():global tokenglobal charactertoken = token + character# IS NUMBERdef digit():if '0' <= character <= '9':return Truereturn False# IS ALPHABETdef letter():if 'A' <= character <= 'Z' or 'a' <= character <= 'z': return Truereturn False# IS IDENTIFIERdef reserve():if token in KEYWORD_LIST:return CATEGORY_DICT[token]else:return 0# RETRACTdef retract():global locationglobal character# location = location - 1character = ""return# MAIN FUNCTIONdef main():global tokenglobal characterglobal locations = getchar()getbe()if 'a' <= s <= 'z' or 'A' <= s <= 'Z':while letter() or digit():concatenation()location = location + 1character = all_string[location]retract()c = reserve()if c == 0:TOKENTABLE.append(token)print("这是标识符:{'", token, "':'", TOKENTABLE.index(token), "'}") else:KEYWORDTABLE.append(token)print("这是保留字:", CATEGORY_DICT[token])elif '0' <= s <= '9':while digit():concatenation()location = location + 1character = all_string[location]retract()CONSTANTTABLE.append(token)print("这是常数:{'", token, "':'", CONSTANTTABLE.index(token), "'}") elif s in OPERATOR_LIST1:location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in OPERATOR_LIST2:location = location + 1character = all_string[location]if character == '=':OPERATORTABLE.append(s + character)print("这是双操作符:", CATEGORY_DICT[s + character])else:retract()location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in SEPARATOR_LIST:location = location + 1SEPARATORTABLE.append(s)print("这是分隔符:", CATEGORY_DICT[s])else:location += 1UNDEFINEDTABLE.append(s)print("error:undefined identity :'", s, "'")if __name__ == '__main__':character = ""token = ""all_string = read_file("program.txt", "r") location = 0while location + 1 < len(all_string): main()print('KEYWORDTABLE:', KEYWORDTABLE)print('TOKENTABLE:', TOKENTABLE)print('CONSTANTTABLE:', CONSTANTTABLE)print('OPERATORTABLE:', OPERATORTABLE)print('SEPARATORTABLE:', SEPARATORTABLE) 运行结果:2.LL(1)分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i输入串:i+i*i代码:NonTermSet = set() # 非终结符集合TermSet = set() # 终结符集合First = {} # First集Follow = {} # Follow集GramaDict = {} # 处理过的产生式Code = [] # 读入的产生式AnalysisList = {} # 分析表StartSym = "" # 开始符号EndSym = '#' # 结束符号为“#“Epsilon = "~" # 由于没有epsilon符号用“~”代替# 构造First集def getFirst():global NonTermSet, TermSet, First, Follow, FirstAfor X in NonTermSet:First[X] = set() # 初始化非终结符First集为空for X in TermSet:First[X] = set(X) # 初始化终结符First集为自己Change = Truewhile Change: # 当First集没有更新则算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:k = 0Continue = Truewhile Continue and k < len(Y):if not First[Y[k]] - set(Epsilon) <= First[X]: # 没有一样的就添加,并且改变标志if Epsilon not in First[Y[k]] and Y[k] in NonTermSet and k > 0: # Y1到Yi候选式都有~存在Continue = Falseelse:First[X] |= First[Y[k]] - set(Epsilon)Change = Trueif Epsilon not in First[Y[k]]:Continue = Falsek += 1if Continue: # X->~或者Y1到Yk均有~产生式First[X] |= set(Epsilon)# FirstA[Y] |= set(Epsilon)# 构造Follow集def getFollow():global NonTermSet, TermSet, First, Follow, StartSymfor A in NonTermSet:Follow[A] = set()Follow[StartSym].add(EndSym) # 将结束符号加入Follow[开始符号]中Change = Truewhile Change: # 当Follow集没有更新算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:for i in range(len(Y)):if Y[i] in TermSet:continueFlag = Truefor j in range(i + 1, len(Y)): # continueif not First[Y[j]] - set(Epsilon) <= Follow[Y[i]]:Follow[Y[i]] |= First[Y[j]] - set(Epsilon) # 步骤2 FIRST(β)/~ 加入到FOLLOW(B)中。
编译原理 LR分析法实验报告
实验五、LR分析法实验报告计算机与信息技术学院程序功能描述通过设计、编写和构造LR(0)项目集规范簇和LR 分析表、对给定的符号串进行LR 分析的程序,了解构造LR(0)分析表的步骤,对文法的要求,能够从文法G 出发生成LR(0)分析表,并对给定的符号串进行分析。
要求以表格或图形的方式实现。
G[E]:E→aA∣bBA→cA∣dB→cB∣d设计要求:(1)构造LR(0)项目集规范簇;要求输入LR(0)文法时,可以直接输入,也可以读取文件,并能够以表格的形式输出项目集规范簇集识别活前缀的有穷自动机(2)构造LR(0)分析表。
要求要求输入LR(0)文法时,可以直接输入,也可以读取文件;输出项目集规范簇,可以调用前一处理部分的结果,输出为LR(0)分析表(3)LR(0)分析过程【移进、归约、接受、报错】的实现。
要求调用前一部分处理结果的分析表,输入一个符号串,依据LR(0)分析表输出与句子对应的语法树,或直接以表格形式输出分析过程。
主要数据结构描述程序结构描述1.首先要求用户输入规则,并保存,分析出规则的数目,规则里的非终结符号和终结符号等信息,为下一步分析备用。
2.根据产生式构造分析表,首先分析每个状态里有哪些产生式,逐步将状态构造完整,最后的规约状态数应该等于产生式的个数。
3.在构造状态的时候,首先将所有的内容均填为出错情况,在每一步状态转换时可以将移进项目填进action表中,对于最后的规约项目,则再用规约覆盖掉之前填的移进。
4.要求用户输入分析串,并保存在输入序列数组中。
5.每一步根据当前的状态栈栈顶状态和输入符号查分析表,若是移进,则直接将符号和相应的状态添进栈中,否则弹出与产生式右部相同个数的字符和状态,并用剩下的状态和产生式的左部在goto表中进行查找,将非终结符和得到的状态压入两个栈内。
6.无论是规约还是移进都要输出当前三个栈内保存内容的情况。
7.如果碰到acc则输出accept,若碰到error则输出error,否则则继续进行规约和移进,不进行结果输出,直至输出接受或出错。
编译原理课程设计--LR(0)分析器自动构造程序的实现
衡阳师范学院工科课程设计 -《编译原理》课程设计报告题目:LR(0)分析器自动构造程序的实现学号:13190207姓名:谭金星班级:1302指导教师:陈琼老师日期:2016年6月20日目录第一章概述 (3)第二章设计的基本原理 (4)2.1 识别文法的LR(0)项目集规范族的构造 (4)2.2 LR(0)分析表的构造 (4)2.3 LR(0)分析器总控程序构造 (5)第三章程序设计 (6)3.1 程序总体构架 (6)3.2 程序存储结构 (7)3.2.1 符号表存储结构 (7)3.2.2 产生式表存储结构 (7)3.2.3 项目集规范族表存储结构 (8)3.2.4 LR(0)分析表存储结构 (9)3.3 程序算法 (9)3.3.1 项目集规范族的构造 (9)3.3.2 LR(0)分析表构造 (10)第四章程序测试 (11)4.1 符号表测试 (11)4.2 产生式表测试 (12)4.3 项目集规范族表测试 (12)4.4 LR(0)分析表测试 (13)4.5 LR(0)分析器测试 (13)第五章总结和展望 (14)附录 (16)参考文献 (17)一概述本课程设计完成了以下内容:1. 实现了对任意给定的文法G,识别文法活前缀的DFA、DFA的状态转化矩阵及(0)LR项目集规范族的构造;2. 判断该文法是否为(0)LR分析表的构造,并输出到指定文LR文法,实现了(0)件中;3. 实现了(0)LR分析器总控程序,对输入的表达式进行文法分析。
4.在VC++6.0程序上运行二 设计的基本原理本课程设计的核心算法错误!未找到引用源。
主要有三点:1. 识别文法活前缀的DFA 、DFA 的状态转化矩阵及(0)LR 项目集规范族的构造;2. (0)LR 分析表的构造;3.(0)LR 分析器总控程序的构造。
2.1 识别文法的LR(0)项目集规范族的构造采用CLOSURE ε-(闭包)的构造一个文法G 的(0)LR 项目规范簇。
编译原理及实现技术:14.语法分析_LR(0)方法_2_SLR(1)
T→• id T→• ( E )
(
E
7
+
T→(E• ) E→E• +T
-
)
8
T→(E) •
1.1 LR分析模型
Input a1 … ai … an #
St Xt
……
LR分析驱动器
Output
Stack
action goto
LR分析表
4
1.2.1 LR分析表
Action表: 状态×(VT∪{#})动作
3 5 5 5
21
限定条件 语法分析表单值
LR(0)和SLR(1)分析能力对比 LR(0)只看分析栈的内容,不考虑当前输
入符;SLR(1)考虑输入符,用follow集来 解决冲突,因此SLR(1)要比LR(0)分析能 力强。
20
a*a*a 状态栈
0 02 03 034 0342 0343 03434 034342 034343 034345 0345 01
10
1.4 LR驱动程序
归约:若当前格局为 (#S1S2…Sn,#X1X2…Xn,aiai+1…an#),且 Action(ISn, a)=Rj,aVT{#},则按照第j个产生式 进行归约,符号栈和状态栈相应元素退栈,归约后 的文法符号入栈。假设第j个产生式为A,k=|| (=Xn-k+1…Xn),则归约后的格局变为: (#S1S2…Sn-kS,#X1X2…Xn-kA,aiai+1…an#) 其中S=Goto(Sn-k, A)。
action(ISk, a)=Si,表示移入动作。 若A•ISk,则对任意aVT,aFollow(A),令
action(ISk, a)=Rj,其中产生式A的编号为j,表示用 编号为j的产生式进行归约。 若Z•ISk,且Z为拓广产生式的左部非终极符(文法 的开始符),则action(ISk, #)=Accept。 其它情形,则Error(n),表示出错标志,也可不填。 goto矩阵: 若GO(ISk, A)=ISi,AVN,则goto(ISk, A)=i。
LR(0)分析法的实现编译原理课程设计
LR(0)分析法的实现编译原理课程设计《编译原理》课程设计报告LR(0)分析法的实现学院(系):班级:学生姓名:学号指导教师:时间:从2007 年12月17日到2007年 12月29日目录1.课程设计的目的 (2)2.课程设计的内容及要求 (2)3.实现原理 (3)3.1 LR分析器结构 (3)3.2 LR分析法寻找可归约句柄的依据 (3)3.3 LR分析器的核心 (4)3.4 LR分析器的总控程序 (4)3.5 具体过程分析如下: (5)3.6 LR(0)分析表构造基本思想 (5)3.7 构造LR(0)分析表的方法 (6)3.7.1生成文法G的LR(0)项目 (6)3.7.2 由项目构成识别文法活前缀的DFA (6)3.7.3将所得DFA确定化 (6)3.7.4 LR(0)项目集规范簇的自动构造 (7)3.7.5 LR(0)分析表的构造算法 (7)4.算法实现流程图 (8)5.测试数据 (9)6.结果输出及分析 (10)7.软件运行环境及限制 (14)8.心得体会 (15)9.参考文献 (15)1.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。
同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。
2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。
2.文法采用常用的方式进行描述,例如:S→aA。
3.以文件方式读取文法。
4.求出项目集规范族(即所有的状态)。
5.给出状态间的关系。
6.给出LR(0)分析表。
7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。
3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。
对所有的LR分析器总控程序都是相同的。
(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
编译原理lr分析
编译原理lr分析编译原理是计算机科学中的一个重要领域,涉及到将源代码转化为可执行代码的过程。
LR分析是编译原理中一种常用且有效的语法分析方法,它通过构建自底向上的语法分析表格,可以对大部分上下文无关文法进行分析。
1. 简介LR分析是一种基于有穷状态自动机模型的语法分析方法,它基于Look-Ahead操作来向前预测分析所需的动作。
LR分析是一种自底向上的语法分析方法,从输入串右侧开始构建句子,直到最后归约为文法的起始符号。
2. LR分析表格LR分析表格是LR分析算法的核心,它将输入符号和状态作为表格的行和列,并填充相应的动作和转移信息。
LR分析表格一般分为动作表和转移表两部分。
在动作表中,我们记录了各个状态下的移进(shift)、归约(reduce)和接受(accept)等动作。
在转移表中,记录了各个状态下的状态转移信息。
3. LR分析算法步骤LR分析算法的主要步骤如下:步骤1: 构建文法的项集族根据给定的上下文无关文法,利用闭包和转移规则构建项集族,形成项目集的有限状态机。
步骤2: 构建LR(0)自动机在项集族的基础上,通过状态间的转移关系构建LR(0)自动机,确定自动机的开始状态和结束状态。
步骤3: 构建LR(0)分析表根据LR(0)自动机,填充LR(0)分析表的动作和转移信息,用于后续的分析过程。
步骤4: 使用LR(0)分析表进行分析利用构建好的LR(0)分析表格,根据输入符号和当前状态,执行相应的移进、归约和接受动作,直到完成分析或出现错误。
4. LR分析的优势和应用相比其他的语法分析方法,LR分析具有以下优势:- 适用性广泛:LR分析适用于大部分上下文无关文法的分析,能够应对复杂的语法结构。
- 自底向上:LR分析从输入串的右侧开始构建句子,逐步归约为文法的起始符号,更为高效。
- 错误检测:LR分析能够及时发现语法错误,并给出相应的错误提示,提高了代码的可靠性和稳定性。
LR分析在实际编译器的设计和实现中得到了广泛的应用。
编译原理LR0分析过程的实现
淮北师范大学编译原理课程设计课题名称:LR(0)分析过程的实现班级:2014级非师2班学号:20141202109姓名: 夏涛目录1.课程设计的目的22.课程设计的内容及要求23.实现原理23.1 LR分析器结构23.2 LR分析法寻找可归约句柄的依据33.3 LR分析器的核心33.4 LR分析器的总控程序43.5 具体过程分析如下:43.6 LR(0)分析表构造基本思想43.7 构造LR(0)分析表的方法53.7.1生成文法G的LR(0)项目53.7.2 由项目构成识别文法活前缀的DFA53.7.3将所得DFA确定化53.7.4 LR(0)项目集规范簇的自动构造63.7.5 LR(0)分析表的构造算法74.算法实现流程图75.测试数据86.结果输出及分析97.软件运行环境及限制128.心得体会139.参考文献131.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。
同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。
2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。
2.文法采用常用的方式进行描述,例如:S→aA。
3.以文件方式读取文法。
4.求出项目集规范族(即所有的状态)。
5.给出状态间的关系。
6.给出LR(0)分析表。
7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。
3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。
对所有的LR分析器总控程序都是相同的。
(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3) 分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
北邮编译原理实验 LR语法分析 实验报告
LR语法分析实验报告班级:2010211308 姓名:杨娜学号:10211369一.题目:LR语法分析程序的设计与实现二.设计目的:(1)了解语法分析器的生成工具和编译器的设计。
(2)了解自上而下语法分析器的构造过程。
(3). 理解和掌握LR语法分析方法的基本原理;根据给出的LR)文法,掌握LR分析表的构造及分析过程的实现。
(4)掌握预测分析程序如何使用分析表和栈联合控制实现LR分析。
三.实验内容:编写语法分析程序,实现对算术表达式的语法分析,要求所分析算数表达式由如下的文法产生:E->E+T|E-T|TT->T/F|T*F|FF->i|n|(E)四.实验要求:编写LR语法分析程序,要求如下:(1)构造识别所有活动的DFA(2)构造LR分析表(3)编程实现算法4.3,构造LR分析程序五.算法流程分析程序可分为如下几步:六.算法设计1.数据结构s :文法开始符号line :产生式的个数G[i][0] :产生式的标号Vt[] :终结符Vn[] :非终结符id :项目集编号Prjt *next :指示下一个项目集Prjt[]:存储项目的编号,prjt[0]项目编号的个数Pointafter[] :圆点后的字符,pointafter[0]为字符个数Prjset*actorgo[]:存储出度Pointbefore:圆点前面的字符Form:动态数组下标,同时作为符号的编号Vn[] :非终结符序列Vt[]:终结符序列2.LR分析器由三个部分组成(1)总控程序,也可以称为驱动程序。
对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
分析器的动作就是由栈顶状态和当前输入符号所决定。
编译原理LR(0)分析过程的实现
编译原理LR(0)分析过程的实现淮北师范大学编译原理课程设计课题名称:LR(0)分析过程的实现班级:2014级非师2班学号:20141202109姓名: 夏涛目录1.课程设计的目的 (2)2.课程设计的内容及要求 (2)3.实现原理 (2)3.1 LR分析器结构 (2)3.2 LR分析法寻找可归约句柄的依据 (3)3.3 LR分析器的核心 (3)3.4 LR分析器的总控程序 (4)3.5 具体过程分析如下: (4)3.6 LR(0)分析表构造基本思想 (4)3.7 构造LR(0)分析表的方法 (5)3.7.1生成文法G的LR(0)项目 (5)3.7.2 由项目构成识别文法活前缀的DFA (5) 3.7.3将所得DFA确定化 (5)3.7.4 LR(0)项目集规范簇的自动构造 (6)3.7.5 LR(0)分析表的构造算法 (7)4.算法实现流程图 (7)5.测试数据 (8)6.结果输出及分析 (9)7.软件运行环境及限制 (12)8.心得体会 (13)9.参考文献 (13)1.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。
同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。
2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。
2.文法采用常用的方式进行描述,例如:S→aA。
3.以文件方式读取文法。
4.求出项目集规范族(即所有的状态)。
5.给出状态间的关系。
6.给出LR(0)分析表。
7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。
3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。
对所有的LR分析器总控程序都是相同的。
(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
淮北师范大学编译原理课程设计课题名称:LR(0)分析过程的实现班级:2014级非师2班学号:*************: **目录1.课程设计的目的 (2)2.课程设计的内容及要求 (2)3.实现原理 (2)3.1 LR分析器结构 (2)3.2 LR分析法寻找可归约句柄的依据 (3)3.3 LR分析器的核心 (3)3.4 LR分析器的总控程序 (4)3.5 具体过程分析如下: (4)3.6 LR(0)分析表构造基本思想 (4)3.7 构造LR(0)分析表的方法 (5)3.7.1生成文法G的LR(0)项目 (5)3.7.2 由项目构成识别文法活前缀的DFA (5)3.7.3将所得DFA确定化 (5)3.7.4 LR(0)项目集规范簇的自动构造 (6)3.7.5 LR(0)分析表的构造算法 (7)4.算法实现流程图 (7)5.测试数据 (8)6.结果输出及分析 (9)7.软件运行环境及限制 (12)8.心得体会 (13)9.参考文献 (13)1.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。
同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。
2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。
2.文法采用常用的方式进行描述,例如:S→aA。
3.以文件方式读取文法。
4.求出项目集规范族(即所有的状态)。
5.给出状态间的关系。
6.给出LR(0)分析表。
7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。
3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。
对所有的LR分析器总控程序都是相同的。
(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3) 分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
3.2 LR分析法寻找可归约句柄的依据1)规范归约的关键问题是找句柄。
2)问题不在于“历史”与“现实”,而是如何基于“历史”对未来“展望”,“展望”可能存在相当多的可能性。
3)一般只是使用简化了的“展望”信息,以便能构造一个可行的分析算法。
4)一个LR分析器实际上是一个带有下推栈的确定的有限状态自动机。
可将一个“历史”与这个“历史”下的展望信息综合为抽象的一个状态5)下推栈可用于存放由“历史”及相应“展望”信息形成的抽象状态。
6)下推栈内的每个状态都概括了从分析开始到归约阶段的全部“历史”和“展望”信息,因此。
栈顶的状态可用于决定当前动作,即,LR分析器的每步动作可由栈顶状态和读头下符号唯一确定。
3.3 LR分析器的核心1、核心分析表2、分析表构成a)动作表(ACTION)ACTION[S,a]表示在当前状态S下,面临读头下符号a所应采取的动作。
b)转向表(GOTO)GOTO[S,X]:若X∈VT,表示在当前状态下,读入a应转向什么状态;若X∈VN,表示当前栈顶句柄归约成X后,应转向什么状态。
c)栈结构图d)分析表格式3.4 LR分析器的总控程序总控程序的动作是根据当前栈顶状态Sm和读头下符号ai查表决定。
1、移进把(Sm, ai)的下一状态S‘=GOTO[Sm,ai]连同读头下符号推进栈内,栈顶成(S’, ai),而读头前进一格;2、归约指用产生式Aα→进行归约。
若α的长度为γ,则弹出栈顶γ项,使栈顶状态变为Sm- γ,然后将(Sm- γ,A)的下一状态S’=GOTO[Sm- γ,A]连同非终结符A一起推进栈内,栈顶变为(S’,A)。
读头不动,即不改变现行输入符号。
3、接受宣布分析成功,退出总控程序。
4、报错报告输入串含有错误,调用相应错误错误处理程序。
3.5 具体过程分析如下:分析器的动作就是由栈顶状态和当前输入符号所决定。
LR分析器结构:其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。
状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。
ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。
动作有四种可能:(1) 移进:action[i,a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。
:当在栈顶形成句柄时,则归约为相应的非(2) 归约:action[i,a]=rk终结符A,即文法中有A->B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。
(3) 接受acc:当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。
(4) 报错:当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。
3.6 LR(0)分析表构造基本思想只根据“历史”信息识别呈现于栈顶的句柄,而不考虑“展望”信息的状态。
活前缀1、定义在规范归约的句型中,不含有句柄以后任何符号的前缀称为活前缀。
它有两种情况:归态活前缀和非归态活前缀。
2、归态活前缀活前缀的尾部正好是句柄之尾,这时可以进行归约。
归约之后又会成为另一句型的活前缀。
3、非归态活前缀句柄尚未形成,需要继续移进若干符号之后才能形成句柄。
3.7 构造LR(0)分析表的方法3.7.1生成文法G的LR(0)项目对文法G的每个产生式右部添加一个圆点,称为G的一个LR(0)项目(简称项目)3.7.2 由项目构成识别文法活前缀的DFA1)对于一个文法G,我们可以构造一个有限自动机,它能识别G的所有活前缀。
2)由于产生式右部的符号串就是句柄,若这些符号串都已进栈,则表示它已处于归态活前缀,若只有部分进栈,则表示它处于非归态活前缀。
要想知道活前缀有多大部分进栈了,可以为每个产生式构造一个自动机,由它的状态来记住当前情况,这时,我们把“状态”称为“项目”。
这些自动机的全体就是能识别所有活前缀的有限自动机。
3.7.3将所得DFA确定化(1)文法G的LR(0)项目生成在文法的每个产生式右部添加一个圆点,就成为G的一个LR(0)项目。
例如,产生式A → XYZ对应四个项目A→•XYZ 预期要归约的句柄是XYZ,但都未进栈A→X•YZ 预期要归约的句柄是XYZ,仅X进栈A→XY•Z 预期要归约的句柄是XYZ,仅XY进栈A→X YZ• 已处于归态活前缀,XYZ可进行归约,这个项目也称为归约项目。
(2)产生式右部符号串的长度为n,则可以分解为n+1个项目。
(3)产生式Aε→只有一个项目A→•。
由项目构成识别文法活前缀的NFA1、将文法进行拓广,保证文法开始符号不出现在任何产生式右部,即增加产生式S`→S,并令S`→• S作为初态项目;2、凡圆点在串的最右边的项目称终态项目或称归约项目,而S`→S • 称为接受项目;3、设项目i为X →X1…Xi-1•Xi…Xn, 项目j为X →X1… Xi • Xi+1 …Xn ,则从项目i画一弧线射向j,标记为Xi , Xi是终结符则称为移进,Xi是非终结符则称为待约;4、若项目i为Xα→•Aβ,其中A是非终结符,则从i项目画ε弧射向所有A→• γ的项目,∈γV*1)构造出的NFA是包含有ε串的NFA,可以使用子集法使之确定化,使之成为一个以项目集为状态的DFA,这个DFA就是建立LR分析算法的基础。
2)相应DFA的每个状态是一个项目集,称作LR(0)项目集,整个状态集称为LR(0)项目集规范簇。
3)在DFA的一个状态对应的项目集内,每个项目是“等价”的,即从期待归约的角度看相同。
4)有一个唯一的初态和一个唯一的接受态,但有若干个归约态,表示有若干种活前缀的识别状态。
5)状态反映了识别句柄的情况,即句柄的多大部分已进栈,即知道了历史情况。
6)手工构造文法的项目集规范3.7.4 LR(0)项目集规范簇的自动构造1、拓广文法增加S` →S 产生式,使文法的开始符号不出现在任何产生式右部,从而保证有唯一的接受项目。
2、定义和构造项目集的闭包设I是拓广文法G`的一个项目集,如下定义和构造I的闭包CLOSURE(I):a) I的任何项目都属于CLOSURE(I);b) 若Aα→•Bβ属于CLOSURE(I),B是非终结符,则对任何关于B的产生式Bγ→,项目B→•γ也属于CLOSURE(I);c) 重复执行步骤b)直到CLOSURE(I)不再扩大为止。
3、定义状态转换函数GOGO(I,X)定义为CLOSURE(J),其中I,J都是项目集,X ∈( VN⋃VT),J={任何形如Aα→X•β的项目| Aα→•X∈βI}。
4、构造LR(0)项目集规范族的算法PROC ITEMSETS-LR0{ C:={CLOSURE(S` →•S)} /*初态项目集*/DO{ FOR (对C中每个项目集I和G`中每个文法符号X)IF (GO(I,X)非空且不属于C){把GO(I,X)加入C中}}WHILE C仍然在扩大}3.7.5 LR(0)分析表的构造算法设C={I0,I1,…In},以各项目集Ik(k=0,…,n)的k作为状态序号,并以包含S` →•S的项目集作为初始状态,同时将G`文法的产生式进行编号。
然后按下列步骤填写ACTION表和GOTO表:1、若项目Aα→•aβ属于Ik状态且GO(Ik,a)= Ij,a为终结符,则置ACTION[k,a]=Sj; 即:移进a,并转向Ij状态。
2、若项目Aα→• ∈Ik,则对任何终结符a(包括语句结束符#),置ACTION[k,a]=rj;即根据j号产生式进行归约,其中,j为产生式Aα→的编号。
3、若项目S` →S•属于Ik, 则置ACTION[k,#]=accept,简记为acc;4、若GO(Ik ,A)= Ij,A是非终结符,则置GOTO[k,A]=j;5、分析表中凡不能用步骤1至4填入信息的空白项,均置上“出错标志”。
4.算法实现流程图5.测试数据[终结符]abcd[非终结符]EAB[开始符]E[产生式]E->aAE->bBA->cAA->dB->cBB->d6.结果输出及分析下面是你输入的文法G:非终结符号集合为:{ E, A, B }终结符符号集合为:{ a, b, c, d } G[E]:(1) E->aA(2) E->bB(3) A->cA(4) A->d(5) B->cB(6) B->d下面是生成的拓广文法G':非终结符号集合为:{ $, E, A, B } 终结符符号集合为:{ a, b, c, d } G'[E]:(0) $->E(1) E->aA(2) E->bB(3) A->cA(4) A->d(5) B->cB(6) B->d该文法的项目如下:(1) $->.E(2) $->E.(3) E->.aA(4) E->a.A(5) E->aA.(6) E->.bB(7) E->b.B(8) E->bB.(9) A->.cA(10) A->c.A(11) A->cA.(12) A->.d(13) A->d.(14) B->.cB(15) B->c.B(16) B->cB.(17) B->.d(18) B->d.LR(0)项目规范族如下:I0 = { 1, 3, 6 }I1 = { 2 }I2 = { 4, 9, 12 }I3 = { 7, 14, 17 }I4 = { 5 }I5 = { 10, 9, 12 }I6 = { 13 }I7 = { 8 }I8 = { 15, 14, 17 } I9 = { 18 }I10 = { 11 }I11 = { 16 }图一:读入文法图二:分析文法图三:分析句子:ad图四:生成树7.软件运行环境及限制系统平台:Windows XP/2000软件平台:VC++ 6.08.心得体会归约的时候应该从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i 为修改指针后的栈顶状态。