簡體   English   中英

在球拍/方案中將文本解析為樹

[英]Parsing a text to the tree in Racket/Scheme

因為我正在學習球拍,所以我試圖將我的C ++代碼轉換為球拍。 我的簡化C ++代碼是:

struct Node
{
    char value = '\0';
    std::vector<Node> kids;
    explicit Node(char ch) : value(ch) {}
};

void ParseTree(const std::string& tokens, size_t& i, Node& root)
{
    while (i < tokens.size())
    {
        const Token& token = tokens[i++];
        if (token == '<')   // children begin
        {
            ParseTree(tokens, i, root.kids.back());
        }
        else if (token == '>')  // children end, go up
        {
            return;
        }
        else
        {
            root.kids.emplace_back(token);
        }
    }
}

Node ParseTree(const std::string& s)
{
    size_t i = 0;
    Node root('$');
    ParseTree(Parse(s), i, root);
    return root;
}

如此簡單的代碼。 我對球拍的翻譯是:

(define (parse-tree tokens)
    (if(empty? tokens)
       '()
       (cond
         [(eq? '< (car tokens))
           (list (parse-tree (cdr tokens)))]
         [(eq? '> (car tokens))
          (parse-tree (cdr tokens))]    ; no return, how to step up?
         [else
          (cons (car tokens)(parse-tree (cdr tokens)))])))

這里的問題是我沒有返回(eq?'>(汽車令牌),所以新節點被添加到底部。一個小測試:

(parse-tree '(1 < 2 < 3 4 > > Z < X >))

應該:

'(1 (2 (3 4)) Z (X))

它是:

'(1 (2 (3 4 Z (X))))

如何解決?

原始方法的問題在於,您試圖直接移植一個命令式解決方案,甚至使用按引用傳遞來跟蹤遍歷狀態。 那將行不通,第一步是以功能編程的方式重新考慮解決方案。

使用堆棧數據結構可以更好地解決此類問題(必須跟蹤嵌套結構內部的位置)。 我將使用列表來實現列表堆棧,並使用以下幫助程序將新元素追加到最上面的列表中:

(define (append-top ele stack)
  (cons (append (car stack) (list ele))
        (cdr stack)))

現在為實際解決方案。 假設輸入列表的格式正確,且<>數目相同且順序正確(不執行錯誤檢查):

(define (parse-tree tokens)
  (let parse ([tokens tokens] [stack '(())])
    (cond [(null? tokens)
           ; solution is at the top of the stack, return it
           (car stack)]
          [(eq? (car tokens) '<)
           ; start new sublist at the top of the stack
           (parse (cdr tokens) (cons '() stack))]
          [(eq? (car tokens) '>)
           ; pop top element of the stack, append it to previous
           ; frame, continue with solution where we left it
           (parse (cdr tokens) (append-top (car stack) (cdr stack)))]
          [else
           ; add current element to top of stack
           (parse (cdr tokens) (append-top (car tokens) stack))])))

它按預期工作!

(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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