2017-10-17 7 views
0

J'essaie de créer un analyseur de terminal (pour un combinateur d'analyseurs) à partir de zéro. Mon approche consiste à utiliser regexp-match-positions* sur la chaîne d'entrée et si le motif est trouvé à la première position, alors nous produisons la chaîne fractionnée.Correspondance et séparation par expression régulière à partir du début de la chaîne

C'est ce que j'ai, jusqu'à présent:

#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") 

Mon ALPHA ne semble pas travailler et je pense qu'il est à cause du motif correspondant n'assimilant avec quoi que ce soit. Dans le REPL, (regexp-match-positions* #rx"[a-zA-Z]" "hello") produit ce que je m'attendrais ('((0 . 1) (1 . 2) etc.)), donc je ne comprends pas vraiment pourquoi cela ne correspond pas à (list (cons 0 x) ...). Si je change l'expression régulière à #rx"h", alors il sépare correctement la chaîne; mais évidemment c'est trop spécifique.

(Sur une note connexe: Je ne comprends pas pourquoi je dois (car x) pour obtenir la valeur réelle de l'indice sur les inconvénients correspondants.)

Répondre

0

Il se trouve le problème que je faisais était bien avec mon modèle correspondant à. Je tentais de faire correspondre sur (list (cons 0 x) ...), mais la documentation implique que ne correspondra à une liste d'un ou plusieurs éléments de (0 . x) (où x est arbitraire). Ce n'est pas ce que je veux. Les listes sont une série de cons, donc j'ai changé mes critères correspondants à (cons (cons 0 x) _) et cela me donne ce que je veux.

Cela explique aussi pourquoi je devais (car x) dans ma tentative précédente. Le x trouvé dans (list (cons 0 x) ...) aurait trouvé chaque élément de droite de chaque cons dans la liste, donc il aurait retourné une liste. Par exemple '((0 . 1) (0 . 2) (0 . 3)) aurait correspondu et x serait égal à '(1 2 3).

Donc, mon code est fixe:

(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., je ne ai pas besoin aussi d'utiliser la version de regexp-match-positions avec étoilé pattern matching, FWIW.