从字符串开头按正则表达式匹配和拆分

Match and split by regular expression from start of string

我正在尝试从头开始制作终端解析器(用于解析器组合器)。我的方法是在输入字符串上使用 regexp-match-positions*,如果在第一个位置找到模式,那么我们输出拆分字符串。

到目前为止,这是我得到的:

#lang racket/base

(require racket/match)

(define (make-terminal-parser pattern)
  (define (regexp-match-from-start pattern input)
    (match (regexp-match-positions* pattern input)
      [(list (cons 0 x) ...)
        (let ([index (car x)])
          (values (substring input 0 index)
                  (substring input index)))]

      [_ (error "Not found!")]))

  (lambda (input)
    (regexp-match-from-start pattern input)))

(define ALPHA (make-terminal-parser #rx"[a-zA-Z]"))

(ALPHA "hello")

我的 ALPHA 似乎不起作用,我认为这是因为模式匹配不等同于任何东西。在 REPL 中,(regexp-match-positions* #rx"[a-zA-Z]" "hello") 输出我所期望的 ('((0 . 1) (1 . 2) etc.)),所以我真的不明白为什么它与 (list (cons 0 x) ...) 不匹配。如果我将正则表达式更改为 #rx"h",那么它会正确地拆分字符串;但显然这太具体了。

(相关说明:我不明白为什么我需要 (car x) 才能从匹配的 cons 中获取实际索引值。)

原来我遇到的问题确实是我的模式匹配。我试图在 (list (cons 0 x) ...) 上匹配,但文档暗示它只会匹配 (0 . x) 的一个或多个元素列表(其中 x 是任意的)。这不是我想要的。

列表是一系列 cons,所以我将匹配条件更改为 (cons (cons 0 x) _),这给了我想要的。

这也解释了为什么我在之前的尝试中必须 (car x)(list (cons 0 x) ...) 中的 x 匹配项将匹配列表中每个 cons 的每个右手元素,因此它会返回一个列表。例如 '((0 . 1) (0 . 2) (0 . 3)) 会匹配,x 会等于 '(1 2 3).

所以,我的固定密码是:

(define (make-terminal-parser pattern)
  (define (regexp-match-from-start pattern input)
    (match (regexp-match-positions pattern input)
      [(cons (cons 0 index) _)
          (values (substring input 0 index)
                  (substring input index))]

      [_ (error "Not found!")]))

  (lambda (input)
    (regexp-match-from-start pattern input)))

n.b.,我也不需要使用带有模式匹配的 regexp-match-positions 加星号版本,fwiw.