2017-10-17 82 views
0

我試圖從頭開始編寫終端解析器(用於解析器組合器)。我的方法是在輸入字符串上使用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)獲得實際的指標值進行匹配的利弊。)

回答

0

原來我是有確實與我的模式問題匹配。我試圖在(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))) 

注:另,我也不需要使用regexp-match-positions帶星版採用模式匹配,FWIW。

相關問題