簡體   English   中英

在語句中添加括號

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM