Racket Lisp - 使用 'read' 尝试解析整个输入字符串
Racket Lisp - using 'read' with trying to parse the whole input string
我使用 Racket 中的函数 read 来解析任意输入字符串。
例如,
>(read (open-input-string "(1 (b 1))")) ; ==> returns '(1 (b 1))
在上面的这个例子中,括号是匹配的——问题出在输入字符串上,
其中括号是unmatched/unbalanced,比如
> (read (open-input-string "(+ 1 1)(")) ; ==> returns '(+ 1 1)
在这种情况下 read 忽略输入字符串中的最后一个括号 '(' -
我想 read 尝试解析整个输入字符串,或者在不可能时,
因为不匹配的括号,抛出异常。
谢谢。
read
过程只从输入端口读取单个数据;额外的括号不会在您的代码中引发错误,因为它永远不会到达。一种解决方案是编写一个从输入端口读取直到到达末尾的过程,将结果形式收集在列表中:
(define (read-from-string s)
(let ((input (open-input-string s)))
(let loop ((expr (read input))
(result '()))
(if (eof-object? expr)
(reverse result)
(loop (read input) (cons expr result))))))
如果read
可以成功解析所有表达式,将返回这些表达式的列表;否则将发出错误信号。
交互示例:
scratch.rkt> (read-from-string "(1 (b 1))")
'((1 (b 1)))
scratch.rkt> (read-from-string "(+ 1 2)")
'((+ 1 2))
scratch.rkt> (read-from-string "(+ 1 2) (+ 3 4)")
'((+ 1 2) (+ 3 4))
scratch.rkt> (read-from-string "()")
'(())
scratch.rkt> (read-from-string "(+ 1 1))")
; string::8: read: unexpected `)`
scratch.rkt> (read-from-string "(+ 1 1)(")
; string::8: read: expected a `)` to close `(`
我使用 Racket 中的函数 read 来解析任意输入字符串。 例如,
>(read (open-input-string "(1 (b 1))")) ; ==> returns '(1 (b 1))
在上面的这个例子中,括号是匹配的——问题出在输入字符串上, 其中括号是unmatched/unbalanced,比如
> (read (open-input-string "(+ 1 1)(")) ; ==> returns '(+ 1 1)
在这种情况下 read 忽略输入字符串中的最后一个括号 '(' - 我想 read 尝试解析整个输入字符串,或者在不可能时, 因为不匹配的括号,抛出异常。 谢谢。
read
过程只从输入端口读取单个数据;额外的括号不会在您的代码中引发错误,因为它永远不会到达。一种解决方案是编写一个从输入端口读取直到到达末尾的过程,将结果形式收集在列表中:
(define (read-from-string s)
(let ((input (open-input-string s)))
(let loop ((expr (read input))
(result '()))
(if (eof-object? expr)
(reverse result)
(loop (read input) (cons expr result))))))
如果read
可以成功解析所有表达式,将返回这些表达式的列表;否则将发出错误信号。
交互示例:
scratch.rkt> (read-from-string "(1 (b 1))")
'((1 (b 1)))
scratch.rkt> (read-from-string "(+ 1 2)")
'((+ 1 2))
scratch.rkt> (read-from-string "(+ 1 2) (+ 3 4)")
'((+ 1 2) (+ 3 4))
scratch.rkt> (read-from-string "()")
'(())
scratch.rkt> (read-from-string "(+ 1 1))")
; string::8: read: unexpected `)`
scratch.rkt> (read-from-string "(+ 1 1)(")
; string::8: read: expected a `)` to close `(`