;;; File: pattern-parser Author: John ;;; This parses the pattern syntax except for the parts which need to be ;;; resolved by precedence parsing. ;;; This parses a list of alternating pats & conops. (define (parse-pat) (trace-parser pat (let ((res (parse-pat/list))) (if (null? (cdr res)) (car res) (make pp-pat-list (pats res)))))) ;;; This parses a list of patterns with intervening conops and + patterns (define (parse-pat/list) (token-case (con (let ((pcon (pcon->ast))) (setf (pcon-pats pcon) (parse-apat-list)) (cons pcon (parse-pat/tail)))) (-n (advance-token) ; past - (token-case (numeric (let ((val (literal->ast))) (cons (make pp-pat-negated) (cons (make const-pat (value val)) (parse-pat/tail))))) (else (signal-missing-token "" "negative literal pattern")))) (var (let ((var (var->ast))) (token-case (+k (cons (make var-pat (var var)) (parse-+k-pat))) (@ (let ((pattern (parse-apat))) (cons (make as-pat (var var) (pattern pattern)) (parse-pat/tail)))) (else (cons (make var-pat (var var)) (parse-pat/tail)))))) (_ (let ((pat (make wildcard-pat))) (token-case (+k (cons pat (parse-+k-pat))) (else (cons pat (parse-pat/tail)))))) (else (let ((apat (parse-apat))) (cons apat (parse-pat/tail)))))) (define (parse-+k-pat) (advance-token) ; past + (token-case (k (let ((val (literal->ast))) (cons (make pp-pat-plus) (cons (make const-pat (value val)) (parse-pat/tail))))) (else (signal-missing-token "" "successor pattern")))) (define (parse-pat/tail) (token-case (conop (let ((con (pconop->ast))) (cons con (parse-pat/list)))) (else '()))) (define (parse-apat) (trace-parser apat (token-case (var (let ((var (var->ast))) (token-case (@ (let ((pattern (parse-apat))) (make as-pat (var var) (pattern pattern)))) (else (make var-pat (var var)))))) (con (pcon->ast)) (literal (let ((value (literal->ast))) (make const-pat (value value)))) (_ (make wildcard-pat)) (\( (token-case (\) (**pcon/def (core-symbol "UnitConstructor") '())) (else (let ((pat (parse-pat))) (token-case (\, (**pcon/tuple (cons pat (parse-pat-list '\))))) (\) pat) (else (signal-missing-token "`)' or `,'" "pattern"))))))) (\[ (token-case (\] (make list-pat (pats '()))) (else (make list-pat (pats (parse-pat-list '\])))))) (\~ (let ((pattern (parse-apat))) (make irr-pat (pattern pattern)))) (else (signal-invalid-syntax "an apat"))))) (define (parse-pat-list term) ;; , separated (let ((pat (parse-pat))) (token-case (\, (cons pat (parse-pat-list term))) ((unquote term) (list pat)) (else (signal-missing-token (if (eq? term '\)) "`)'" "`]'") "pattern"))))) (define (parse-apat-list) ;; space separated (token-case (apat-start (let ((pat (parse-apat))) (cons pat (parse-apat-list)))) (else '()))) ;;; The following routine scans patterns without creating ast structure. ;;; They return #t or #f depending on whether a valid pattern was encountered. ;;; The leave the scanner pointing to the next token after the pattern. (define (scan-pat) ; same as parse-pat/list (and (token-case (con (scan-con) (scan-apat-list)) (-n (advance-token) (token-case (numeric (advance-token) '#t) (else '#f))) (var (and (scan-var) (token-case (@ (scan-apat)) (+k (scan-+k)) (else '#t)))) (_ (scan-+k)) (else (scan-apat))) (scan-pat/tail))) (define (scan-pat/tail) (token-case (conop (and (scan-conop) (scan-pat))) (else '#t))) (define (scan-apat) (token-case (var (scan-var) (token-case (@ (scan-apat)) (else '#t))) (con (scan-con)) (literal (advance-token) '#t) (_ '#t) (\( (token-case (\) '#t) (else (and (scan-pat) (token-case (\, (scan-pat-list '\))) (\) '#t) (else '#f)))))) (\[ (token-case (\] '#t) (else (scan-pat-list '\])))) (\~ (scan-apat)) (else '#f))) (define (scan-pat-list term) (and (scan-pat) (token-case (\, (scan-pat-list term)) ((unquote term) '#t) (else '#f)))) (define (scan-apat-list) (token-case (apat-start (and (scan-apat) (scan-apat-list))) (else '#t))) (define (scan-var) (token-case (varid '#t) (\( (token-case (varsym (token-case (\) '#t) (else '#f))) (else '#f))) (else '#f))) (define (scan-con) (token-case (conid '#t) (\( (token-case (consym (token-case (\) '#t) (else '#f))) (else '#f))) (else '#f))) (define (scan-conop) (token-case (consym '#t) (\` (token-case (conid (token-case (\` '#t) (else '#f))) (else '#f))) (else '#f))) (define (scan-+k) (token-case (+k (advance-token) ; past the + (token-case (integer '#t) (else '#f))) (else '#t)))