当您看到“(”并使用“)”关闭它时,如何创建一个新列表。口齿不清 Python

How to make a new List when you see a "(" and close it using ")". Lisp to Python

我想做一个 Lisp 解释器,我只是在标记化后努力翻译它。所以在标记化之后,我的列表看起来像这样。

tokenized = ["(", "car", "'","(", "20", "40", "60", ")", ")"] 

我想要的是将它翻译成看起来像这样的东西

translated = [["CAR", "'", [20, 40, 60]]]

我需要一种在看到“(”时创建新列表并在看到“)”时关闭它的方法。让我知道是否需要更好地解释它,我不擅长解释。

好的,所以这就像递归下降解析器一样工作。每次它看到一个左括号,它都会创建一个新的 list,将其附加到输出列表并向下递归,但使用新列表。每次它看到一个右括号时,它只是 returns 到它之前的位置。递归的基本情况是到达要解析的项目的末尾:

def rdp(items):
    it = iter(items)
    def inner(it, out):
        while True:
            token = next(it)
            if token == '(':
                nxt = []
                out.append(nxt)
                inner(it, nxt)
                continue
            elif token == ')':
                return
            out.append(token)

    nxt = []
    try:
        inner(it, nxt)
    except StopIteration:
        pass
    return nxt

tokenized = ["(", "car", "'","(", "20", "40", "60", ")", ")"]
translated = rdp(tokenized)

按要求输出

注意: 我刚刚编辑它以将 try:except: 移到 inner() 递归函数之外以避免重复异常。

我会用 Lisp 给你一个答案(我假设严格的从左到右顺序求值):

(define (relist tokens)
  (let ((tok #f))
    (define (get)
      (set! tok (car tokens))
      (set! tokens (cdr tokens))
      tok)
    (define (go)
      (cond
        ((null? tokens)
          '())   ; we're done
        ((eq? (get) ")")
          '())   ; done with this level
        ((eq? tok "(")
          (cons (go)     ; open new
                (go)))   ;  level
        (else 
          (cons tok      ; go on with
                (go))))) ; this level
    (go)))

;; testing in DrRacket:

(relist '[1 2 "(" 3 "(" 4 ")" ")" 5]) ;=> '(1 2 (3 (4)) 5)
(relist '[1 2 "(" 3 "(" 4 ")"     5]) ;=> '(1 2 (3 (4) 5))

变量tok 是函数的局部变量。它的范围在这里包括所有内部函数定义以及函数体。

go 的所有调用通过调用 get.

与相同的输入流(列表)tokens 一起工作并向前推进

当收到打开新子列表的信号时,令牌 "(",我们通过递归 non-tail 调用 go(忽略令牌本身)当然)。

否则我们只是使用接收到的令牌并继续,这表示为 go 的尾部调用(两者,在两种情况下)。您自然会用 Python 原生的其他方式来表达这一点。我只是想向您展示它的基本最小结构,在 Lisp 中很好地看到。