[英]Add parenthesis to statement
我在解析字符串並在Python中添加括號時遇到問題。 我的問題之一是該字符串可能以完全括弧的方式輸入(即(01U(1U0))
),也可能根本不輸入(即01U1U0
)。 我似乎無法將其分解的語法是:
A -> e* | (eUe)
e -> any combination of chars from the grammar
e*
優先級高於U
希望這是有道理的。 有人對我如何解析和檢查括號有任何想法嗎?
從LL語法編寫解析器的最簡單方法可能是每個非終端符號都有一個函數。 此函數應該吃掉與一個簡化規則對應的輸入字符串中的字符。 下面是語法對應的解析器
A -> e+ | '(' A 'U' A ')'
e -> '0' | '1'
這不完全是您想要的語法,但是從您提供的示例中可以更輕松地看到。 語法是LL(1),您只需要閱讀一個字符就可以知道如何進行。 以下解析器為這兩個非終結符定義了兩個函數A()和e():
class MySyntaxError(Exception):
def __init__(self, text, index):
self.text = text
self.index = index
def __str__(self):
return "Syntax error at index " + repr(self.index) + ": " + self.text
def parse(input):
global index
index = 0
def eat_char(set):
global index
if index < len(input) and input[index] in set:
index += 1
else:
raise MySyntaxError("expected char in " + repr(set), index)
def e():
eat_char(['0', '1'])
def A():
global index
if index == len(input): # Successfully parsed
return
elif input[index] in ['0', '1']:
while (input[index] in ['0', '1']):
e()
elif input[index] is '(':
eat_char(['('])
A()
eat_char(['U'])
A()
eat_char([')'])
else:
raise MySyntaxError("expected char '0', '1' or '('", index)
A()
if index != len(input): # Parsing didn't reach the end of the string
raise MySyntaxError("parsing ended before the end of the input", index)
def test(string):
try:
parse(string)
print "The string " + string + " have been successfully parsed"
except MySyntaxError as e:
print "The string " + string + " can't be parsed:"
print e
test("(01U(1U0))")
test("(01U(1U0)") # Missing parenthesis, syntax error
test("(01U(1U0)))") # Too many parenthesis, syntax error
test("01U(1U0)") # No parenthesis, syntax error
請注意,使用e *代替e +會使空減少為A,這會使解析器復雜化。
下推自動機隱藏在解析器中。 從語法構建自動機並不是那么簡單。 在這里,PDA只有一種狀態。 我們可以這樣描述自動機:
from state [1]
read a '0' or a '1' and loop into state [1]
read a '(', push the parenthesis and loop into state [1]
read a 'U', when there is an open parenthesis on the top of stack, push the 'U' and loop into state [1]
read a ')', when there is a 'U' on the top of the stack, pop the 'U', pop the opend parenthesis following, and loop into state[1]
有一種直接的方法可以用Python編寫此自動機。 通常,您需要goto來編寫自動機。 每個狀態都綁定到一個標簽,並通過goto完成從一個狀態到另一個狀態的轉換。 不幸的是,Python中沒有goto。 但是,由於您只有一種狀態,因此沒有必要,並且循環將起作用:
def parse(input):
index = 0
stack = [];
def top():
if len(stack) > 0:
return stack[len(stack)-1]
else:
return None
while index < len(input):
if input[index] in ['0', '1']:
pass
elif input[index] is '(':
stack.append('(')
elif input[index] is 'U' and top() == '(':
stack.append('U')
elif input[index] is ')' and top() == 'U':
stack.pop()
stack.pop()
else:
raise MySyntaxError("Unexpected char '" + input[index] + "'", index)
index += 1
if len(stack):
raise MySyntaxError("unterminated input", index)
這是具有顯式堆棧的PDA。 先前的解析器使用程序堆棧而不是隱式堆棧,並且在遞歸調用的數量中記住了括號的數量。 當您要檢查字符串的有效性時,此第二個解析器很有用。 但是,當您想要生成輸入的表示形式(例如抽象語法樹)時,這是不方便的:它們通常是根據語法構建的,因此更容易從第一個解析器生成。 第一個也更易於閱讀,因為您不必計算自動機就可以理解它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.