List LISP查找最后一对括号

List LISP查找最后一对括号,list,lisp,common-lisp,List,Lisp,Common Lisp,我编写的函数必须返回}的位置,该位置对应于它从一开始找到的{的第一个匹配项(我不寻找}的最后一个匹配项)。 例如,给定这种JSON类型的结构化字符串 (成对的-b(强制“[{\'b\':{\'c\':[[1,{\'d\':1}],{\'e\':3}],“'g\':2},{\'a\':2}]”列表) 该功能应 返回子序列->之前的}(与字符串的第一个{成对),{\“a\”:2}”,但返回子序列->之前的位置,\“g\”:2}。。。 但是如果我试着 (paired-b (coerce "[ {\"a

我编写的函数必须返回}的位置,该位置对应于它从一开始找到的{的第一个匹配项(我不寻找}的最后一个匹配项)。 例如,给定这种JSON类型的结构化字符串

(成对的-b(强制“[{\'b\':{\'c\':[[1,{\'d\':1}],{\'e\':3}],“'g\':2},{\'a\':2}]”列表)

该功能应 返回子序列->之前的}(与字符串的第一个{成对),{\“a\”:2}”,但返回子序列->之前的位置,\“g\”:2}。。。 但是如果我试着

(paired-b (coerce "[ {\"a\" : 1} , {\"b\" : 2} ]" 'list))
函数返回所需}的正确位置,即逗号之前的位置。 代码的哪一部分有错误?有没有其他方法来实现这样的功能

(defun paired-b (list)
  (if (position #\{ list)
      (if (< (position #\{ list) (position #\} list))
          (if (eql (position #\{ list) (- (position #\} list) 1))
              (position #\} list :start
                        (+ (position #\{ list)
                           (paired-b (subseq list (+ (position #\{ list) 1))) 1))
            (position #\} list :start
                      (+ (position #\{ list)
                         (paired-b (subseq list (+ (position #\{ list) 1) 2))))) 0) 0))
打开=计数{,关闭=计数},位置=位置od索引


这段代码似乎可以工作,但在解析器内部,其他函数调用它,如果我解析长字符串,程序就会发生堆栈溢出。

从那里查找第一个
{
.Loop,计算嵌套级别。当级别达到0时,您就找到了匹配项

(defun curly-positions (string)
  "Looks for the first #\{ in `string', then finds the matching #\}.
Returns these positions as two values."
  (let* ((open-position (position #\{ string :test #'char=))
         (close-position (loop :for i :upfrom (1+ open-position)
                               :for c := (char string i)
                               :for level := 1
                                 :then (case c
                                         (#\{ (1+ level))
                                         (#\} (1- level))
                                         (t level))
                               :when (zerop level)
                                 :do (return i))))
    (values open-position
            close-position))))

(not(null…)
数字与
eql
=
比较,但与
eq
不比较。多次
(position#\somechar x)
是丑陋的。写
(eql(…
)而不是
(eql(
)。因此,通过一些工作,您可能最终实现这一点,但是:强制向量(字符串)你可以使用
loop
for over
或者干脆用
aref
来代替。另外,要注意如何处理格式错误的输入。还要注意字符串中的
{
(和
\”
)。如果您的最终目标是解析,我建议您使用/修改库或使用流(例如,使用字符串输入的
),只需编写一个完整的解析器,一次检查一个字符。
(defun curly-positions (string)
  "Looks for the first #\{ in `string', then finds the matching #\}.
Returns these positions as two values."
  (let* ((open-position (position #\{ string :test #'char=))
         (close-position (loop :for i :upfrom (1+ open-position)
                               :for c := (char string i)
                               :for level := 1
                                 :then (case c
                                         (#\{ (1+ level))
                                         (#\} (1- level))
                                         (t level))
                               :when (zerop level)
                                 :do (return i))))
    (values open-position
            close-position))))