Python Preliminary Experiment 1 Grammar Reading and Output Compilation Principles

The content of this article:

1. Design a data structure representing the grammar
; 2. Read the grammar from the text file, use the defined data structure to store the grammar, and output

Edit a text file g.txt, enter the following content in the file:

S->Qc;
S->c;
Q->Rb;
Q->b;
R->Sa;
R->a;

The output form of the above grammar arrangement is as follows: 

S->Qc|c;
Q->Rb|b;
R->Sa|a;

 Inputs like this are also supported:

S->Qc|c|cc|da|Q1
Q->Rb|b|V
R->Sa|a|cV2
Q1->aa|bd
V2->d|Q2
Q2->a
V->V2|e

result:

S->Qc|c|cc|da|Q1;
Q->Rb|b|V;
R->Sa|a|cV2;
Q1->aa|bd;
V2->d|Q2;
Q2->a;
V->V2|e;

code show as below:

def GetGrammar(grammar):  # 输出文法
    global non_terminator, production
    for i in grammar[non_terminator]:  # 遍历非终结符
        print(i + '->', end='')  # 前部
        for j in range(len(grammar[production][i])):  # 根据非终结符遍历该终结符的产生式
            if j > 0:
                print('|', end='')
            for k in grammar[production][i][j]:
                print(k, end='')
        print(';')


def LongStr(sting, list_data):  # 从列表中寻找匹配最长的项
    maxlen = 0  # 最长的匹配字符串长度
    maxstr = -1  # 匹配的最长字符串位置
    for i in range(len(list_data)):  # 遍历
        if sting.startswith(list_data[i]):  # 判断字符串是否以list[i]开头
            leni = len(list_data[i])
            if leni > maxlen:  # 如果新匹配字符串比原来长,替换
                maxlen = leni
                maxstr = i
    return maxlen, maxstr


def PrimaryTreatment(grammar):  # 初步处理,使得产生式内部分开
    global non_terminator, production
    for i in grammar[non_terminator]:  # 遍历非终结符
        for j in range(len(grammar[production][i])):  # 根据非终结符遍历该终结符的产生式
            k = 0  # 所处位置指针
            str_production = grammar[production][i][j][0]  # 产生式字符串
            new_production = []  # 准备存初步处理后的产生式
            while k < len(str_production):
                maxlen, maxstr = LongStr(str_production, grammar[non_terminator])  # 寻找匹配最长的终结符
                if maxlen == 0:  # 没找到
                    new_production.append(str_production[k])  # 分出一个终结符
                    k += 1
                else:  # 找到了
                    new_production.append(str_production[k:k + maxlen])  # 分出一个非终结符
                    k += maxlen
            grammar[production][i][j] = new_production  # 产生式替换
            pass


def OpenGrammar(file):  # 从文件中打开(读取)文法。并作初级处理(产生式中各个非终结符和终结符分开)
    global non_terminator, production
    file = open(file)  # 读取文件
    non_terminator = '非终结符'
    production = '产生式'
    grammar = {non_terminator: [], production: {}}
    while i := file.readline():  # 一行一行的读取,并赋值给i
        for j in range(len(i)):  # 遍历i中每一个字符
            if i[j] == '-' and i[j + 1] == '>':  # 分割前面的字符就是非终结符
                if not i[0:j] in grammar[non_terminator]:  # 该非终结符还没有记录
                    grammar[non_terminator].append(i[0:j])  # 加入进去
                    grammar[production][i[0:j]] = []
                k = j + 2  # 直达产生式右部第一个字符
                for l in range(len(i)+1):   # +1是为了处理最后一行又不带分号又不带回车的情况
                    # 这里由于用了断路特性即l == len(i)成立后不会运行后面的,从而不会产生数组越界报错
                    if l == len(i) or i[l] == ';' or i[l] == '\n':  # 往后找到最后一个,结束
                        grammar[production][i[0:j]].append([i[k:l]])  # 添加到后面
                        break
                    if i[l] == '|':  # 遇到了中断
                        grammar[production][i[0:j]].append([i[k:l]])  # 添加到后面
                        k = l + 1  # 并且左边标记右移
                break
    file.close()
    PrimaryTreatment(grammar)
    return grammar


global non_terminator, production
file = 'g.txt'  # 文件位置
grammar = OpenGrammar(file)
GetGrammar(grammar)

 

Guess you like

Origin blog.csdn.net/weixin_58196051/article/details/130629231