判断文法类别课程设计,文法的计算机表示

说明:文法的空字符串以@表示

实现:大写字母和小写字母分别表示终结符号以及非终结符号。(只能识别字母)

         用<>和不带<> 分别表示终结符号以及非终结符号

         产生式可以用->,::=表示

代码的部分解释:

1.Vn,Vt,分别为集合类型,在统计终结符号集以及非终结符号集时会自动去重。

2.left,right,分别会统计每一条产生式的左部以及右部的字符串。

3.left_num,right_num:存储类型为元组,分别表示左部以及右部出现的终结符号,以及非终结符号的个数。

4.对以<>格式的产生式,以堆栈进行解析,因此,需要逆序入栈。

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 15 20:48:32 2019

@author: Administrator
"""
import re
Vn=set();Vt=set();flag=-1;left=[];right=[];left_num=[];right_num=[]#二维元组,分别表示非终结符号以及终结符号的个数
class Stack(object):
    """栈"""
    def __init__(self):
         self.items = []

    def is_empty(self):
        """判断是否为空"""
        return self.items == []

    def push(self, item):
        """加入元素"""
        self.items.append(item)

    def pop(self):
        """弹出元素"""
        return self.items.pop()

    def peek(self):
        """返回栈顶元素"""
        return self.items[len(self.items)-1]

    def size(self):
        """返回栈的大小"""
        return len(self.items)
    
    
def jiexi1(s,f): #解析由<>定义的文法
    stack=Stack()
    vn_num=0;vt_num=0
    for c in s[::-1]:#使用堆栈,因此为了保证顺序,逆序访问
        if c=='>':
            v=''
            while stack.size()!=0:
                v+=stack.peek()
                stack.pop()
            if v!='':
                Vt.add(v)
                vt_num+=1
            continue
        if c=='<':
            v=''
            while stack.size()!=0:
                v+=stack.peek()
                stack.pop()
            Vn.add(v)
            vn_num+=1
            continue
        stack.push(c)#非<>的元素入栈
    v=''#保证最后一个非<>的元素可以被访问
    while stack.size()!=0:
        v+=stack.peek()
        stack.pop()
    if v!='':
        Vt.add(v)
        vt_num+=1
    if(f==0):
        left_num.append((vn_num,vt_num))
    if(f==1):
        right_num.append((vn_num,vt_num))
  
def jiexi2(s,f):#处理大学字母表示非终结符号,小写字母表示终结符号集的情况
    vn_num=0;vt_num=0
    for c in s:
        if c.isupper():
            Vn.add(c)
            vn_num+=1;
        if c.islower():
            Vt.add(c)
            vt_num+=1
    if(f==0):
        left_num.append((vn_num,vt_num))
    if(f==1):
        right_num.append((vn_num,vt_num))
        
def getLeftRight():
    with open("C:/Users/Administrator/Desktop/新建文件夹/编译原理.txt","r") as f:
        global lines
        lines=f.readlines()
        if(''.join(lines).find("<")!=-1):
            global format_wenfa
            format_wenfa=1
        else:
            format_wenfa=2
        for line in lines:
            s=line.strip().partition("::=")
            if(s[2]==""):
                s=line.strip().partition("->")
            left.append(s[0]);right.append(s[2])
        return left,right

def getVnVt():   
    getLeftRight() #判断采用哪一种解析方式
    if format_wenfa==1:
        for v in left: #这里v表示每一条产生式的左部
            jiexi1(v,0)
        for v in right:
            jiexi1(v,1)
    else:
        for v in left:
            jiexi2(v,0)
        for v in right:
            jiexi2(v,1)

def first():
    for k,v in zip([k+v for k,v in left_num],[k+v for k,v in right_num]):#k,v分别表示左边和右边
        if k>v or k==0 or v==0:
            return -1
    return 1
def second():
    for (k,v) in left_num:#left 分别指所有文法的左部
        if k!=1 or v!=0:
            return -1
    return 2
def third():#(Vn,Vt)
    for k,v in left_num:#k,v分别表示终结符号集以及非终结符号集
        if not (k==1 and v==0):
            return -1
    for k,v in right_num:
        if not (k<=1 and v==1):
            return -1;
    return 3
            
def zero():
    for k,v in left_num:#k,v分别表示非终结符号以及终结符号
        if k==0 and v==0:
            return -1
    return 0
if __name__ == '__main__':
    getVnVt()
    flag=third()
    if(flag==-1):
        print("flag1",flag)
        flag=second()
    if(flag==-1):
        print("flag2",flag)
        flag=first()
    if(flag==-1):
        print("flag3",flag)
        flag=zero()
    if(flag!=-1):
        print(flag,"型文法")
    else:
        print("不合格的文法构造")
print("left_num",left_num)
print("right_num",right_num)    
print("left",left)
print("right",right) 
print("Vn:",Vn)
print("Vt:",Vt)
print("P:",[line.strip() for line in lines])
print("S:",left[1])       
     
        
    

由于对python的方法有遗忘,个人感觉可以写的更简单点,但这只是一个作业,所以没想着精细修改。如果大家有什么指教,请不要吝啬,另外,我感觉用Scala写的话代码量可能更少,可以试试。 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实验2 文法的读入、判定和处理 一、实验目的 熟悉文法的结构,了解文法计算机内的表示方法。 二、实验内容 1、 设计一个表示文法的数据结构; 2、 从文本文件中读入文法,利用定义的数据结构存放文法,并输出; 3、 本实验结果将来还有用。 三、实验要求 1、 了解文法定义的4个部分: G(Vn, Vt, S, P) Vn 文法的非终结符号集合,在实验中用大写的英文字母表示; Vt 文法的终结符号集合,在实验中用小写的英文字母表示; S 开始符号,在实验中是Vn集合中的一个元素; P 产生式,分左部和右部,左部为非终结符号中的一个,右部为终结符号或非终结符号组成的字符串,如S->ab|c 2、 根据文法各个部分的性质,设计一个合理的数据结构用来表示文法, 1) 若使用C语言编写,则文法可以设计成结构体形式,结构体中应包含上述的4部分, 2) 若使用C++语言或java语言编写,则文法可以设计成文法类形式,类中至少含有4个数据成员,分别表示上述4个部分 文法数据结构的具体设计由学生根据自己想法完成,并使用C或C++语言或Java实现设计的数据结构。 3、 利用完成的数据结构完成以下功能: 1) 从文本文件中读入文法文法事先应写入文本文件); 2) 根据文法产生式的结构,分析出文法的4个部分,分别写入定义好的文法数据结构的相应部分; 3) 整理文法的结构,判断文法文法类型,是否为0型,1型,2型或3型文法,并输出判断结果; 4) 在计算机屏幕或者文本框中输出文法文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值