简体   繁体   English

弄清楚如何扩展语法(Python)

[英]Figuring out how to expand a grammar (Python)

Im trying to write code that will return an expanding grammar. 我试图编写将返回扩展语法的代码。 so in this example I will specify a length of 3, N = ND will expand it self to N = NDD and then it will expand again to N = NDDD but then exit the program, any advice for making this happen? 所以在这个例子中我将指定长度为3,N = ND将自己扩展为N = NDD然后它将再次扩展到N = NDDD然后退出程序,任何建议实现这一点? I currently tried to do the replace method in printGrammar but as you can see when you run it for some reason NT (the non terminal being replaced, in this example N), and item (the value from the dictionary, in this case ND and D) wont replace and I am left with a list with 'N' instead of what I want which is NDD, can someone please help me? 我目前尝试在printGrammar中执行替换方法但是你可以看到当你运行它时由于某种原因NT(非终端被替换,在这个例子中为N)和item(字典中的值,在本例中为ND和D)不会更换,我留下一个带有'N'的列表而不是我想要的NDD,有人可以帮助我吗?

Binary.txt is: Binary.txt是:

N = N D
N = D
D = 0
D = 1

Code is 代码是

import sys
import string
from collections import defaultdict

#default length of 3
stringLength = 3

#get last argument of command line(file)
if len(sys.argv) == 1:
    #get a length from user
    try:
        stringLength = int(input('Length? '))
        filename = input('Filename: ')
    except ValueError:
        print("Not a number")

elif len(sys.argv) == 2:
    #get a length from user
    try:
        stringLength = int(input('Length? '))
        filename = sys.argv[1]
    except ValueError:
        print("Not a number")

elif len(sys.argv) == 3:
    filename = sys.argv[2]
    stringLength  = sys.argv[1].split('l')[1]
else:
    print("Invalid input!")


#get start symbol
with open(filename, "r") as grammar:
    #read file 
    lines = grammar.readlines()
    start = lines[0].split('=')[0]
    start = start.replace(" ", "")


#checks

#print(stringLength)
#print(filename)
#print(start)
def str2dict(filename):
    result = defaultdict(list)
    with open(filename, "r") as grammar:
        #read file 
        lines = grammar.readlines()
        count = 0

        #loop through
        for line in lines:
            #append info 
            line = line.rstrip()

            result[line[0]].append(line.split('=')[1])

    return result


workingDict = str2dict("Binary.txt")
print(workingDict)


def strings(grammar, start):
    queue = [start]
    while len(queue):
        current = queue.pop(0)
        # for each symbol in the current string
        for n, sym in enumerate(current):
            # if this symbol is a non-terminal
            if sym in grammar:
                # for each rule for this symbol...
                for rhs in grammar[sym]:
                    # replace it with the right part
                    new = current[:n] + rhs + current[n+1:]
                    # does the result contain non-terminals
                    if any(s in grammar for s in new):
                        # yes, place it into the queue
                        queue.append(new)
                    else:
                        # no, return it
                        yield new

for x in strings(workingDict, stringLength):
    print (x)
    if len(x) > 4:
        break

Assuming your grammar is in the form 假设你的语法是在形式

grammar = {
    'N': ['ND', 'D'],
    'D': ['0', '1']
}

the algorithm looks straightforward: 该算法看起来很简单:

  • iterate over the current string (which is initially just one symbol) 迭代当前字符串(最初只是一个符号)
  • if the symbol is a non-terminal, replace it with its production 如果符号是非终端,则将其替换为其生产
  • if the result contains non-terminals, place it in a queue for further processing 如果结果包含非终端,则将其放入队列以进行进一步处理
  • otherwise, return the result (which is a string of terminals) 否则,返回结果(这是一串终端)
  • pick the next "current" string from the top of the queue and continue 从队列顶部选择下一个“当前”字符串并继续

:

def strings(grammar, start):
    queue = [start]
    while len(queue):
        current = queue.pop(0)
        # for each symbol in the current string
        for n, sym in enumerate(current):
            # if this symbol is a non-terminal
            if sym in grammar:
                # for each rule for this symbol...
                for rhs in grammar[sym]:
                    # replace it with the right part
                    new = current[:n] + rhs + current[n+1:]
                    # does the result contain non-terminals
                    if any(s in grammar for s in new):
                        # yes, place it into the queue
                        queue.append(new)
                    else:
                        # no, return it
                        yield new

Usage: 用法:

for x in strings(grammar, 'N'):
    print x
    if len(x) > 4:
        break

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM