Commit 7150e90b 7150e90bf6ff026a7bf31f2f5586aa14c78ebc87 by Sergey Poznyakoff

Use new sieve-register style.

(sieve-preprocess-arguments): New function. Preprocess
and group arguments into optional and positional types.
(sieve-parse-arguments): New function. Parses arguments
to an action or a test.
(sieve-register-action,sieve-register-test): Rewritten.
1 parent a81bb72a
1 #! %BINDIR%/guimb --source 1 #! %BINDIR%/guimb --source
2 # Emacs, its -*- scheme -*-
2 !# 3 !#
3 ;;;; GNU mailutils - a suite of utilities for electronic mail 4 ;;;; GNU mailutils - a suite of utilities for electronic mail
4 ;;;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. 5 ;;;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
...@@ -130,11 +131,19 @@ ...@@ -130,11 +131,19 @@
130 (>= end (1- input-length)) 131 (>= end (1- input-length))
131 (not (char-numeric? 132 (not (char-numeric?
132 (string-ref input-line end)))) 133 (string-ref input-line end))))
133 end))) 134
135 (cond
136 ((char-numeric? (string-ref input-line end))
137 (1+ end))
138 (else
139 end)))))
134 (num (string->number (substring input-line start end))) 140 (num (string->number (substring input-line start end)))
135 (q (string-ref input-line end)) 141 (q (if (< end input-length)
142 (string-ref input-line end)
143 #f))
136 (k 1)) 144 (k 1))
137 (case q 145 (case q
146 ((#f) #f) ;; nothing
138 ((#\K) 147 ((#\K)
139 (set! end (1+ end)) 148 (set! end (1+ end))
140 (set! k 1024)) 149 (set! k 1024))
...@@ -145,11 +154,8 @@ ...@@ -145,11 +154,8 @@
145 (set! end (1+ end)) 154 (set! end (1+ end))
146 (set! k 1073741824)) 155 (set! k 1073741824))
147 (else 156 (else
148 (cond 157 (if (not (delimiter? q))
149 ((char-numeric? q) 158 (lex-error "Unknown qualifier (" q ")"))))
150 (set! end (1+ end)))
151 ((not (delimiter? q))
152 (lex-error "Unknown qualifier (" q ")")))))
153 (set! input-index end) 159 (set! input-index end)
154 (cons 'number (* num k)))) 160 (cons 'number (* num k))))
155 (else 161 (else
...@@ -410,7 +416,8 @@ ...@@ -410,7 +416,8 @@
410 (define (sieve-find-test name) 416 (define (sieve-find-test name)
411 (sieve-syntax-table-lookup sieve-test-table name)) 417 (sieve-syntax-table-lookup sieve-test-table name))
412 418
413 (define (sieve-register-test name function opt-arg-list req-arg-list) 419 (define (sieve-register-test name function req-arg-list opt-arg-list)
420 (DEBUG 100 "sieve-register-test" name req-arg-list opt-arg-list)
414 (cond 421 (cond
415 ((not (list? opt-arg-list)) 422 ((not (list? opt-arg-list))
416 (lex-error "sieve-register-test: opt-arg-list must be a list")) 423 (lex-error "sieve-register-test: opt-arg-list must be a list"))
...@@ -427,10 +434,14 @@ ...@@ -427,10 +434,14 @@
427 (list name function opt-arg-list req-arg-list))))))) 434 (list name function opt-arg-list req-arg-list)))))))
428 435
429 436
437 ;;; sieve-preprocess-arguments: Preprocess and group the arguments. Returns
438 ;;; a cons whose car is a list of all optional arguments, and the cdr is
439 ;;; a list of the rest of the arguments.
440 ;;;
430 ;;; arguments = *argument [test / test-list] 441 ;;; arguments = *argument [test / test-list]
431 ;;; argument = string-list / number / tag 442 ;;; argument = string-list / number / tag
432 443
433 (define (sieve-parse-arguments tag-gram) 444 (define (sieve-preprocess-arguments tag-gram)
434 (do ((opt-list '()) ;; List of optional arguments (tags) 445 (do ((opt-list '()) ;; List of optional arguments (tags)
435 (arg-list '()) ;; List of positional arguments 446 (arg-list '()) ;; List of positional arguments
436 (last-tag #f) ;; Description of the last tag from tag-gram 447 (last-tag #f) ;; Description of the last tag from tag-gram
...@@ -472,17 +483,78 @@ ...@@ -472,17 +483,78 @@
472 (else 483 (else
473 (set! arg-list (append arg-list (list token))))) 484 (set! arg-list (append arg-list (list token)))))
474 #f) 485 #f)
475 ((delimiter token #\[) ;;FIXME: tags are not allowed to take 486 ((delimiter token #\[)
476 ;;string-list arguments.
477 (set! state 'arg)
478 (putback-token) 487 (putback-token)
479 (set! arg-list (append arg-list 488 (cond
480 (list (require-string-list)))) 489 ((and (eq? state 'opt) (pair? last-tag))
481 #f) 490 (cond
491 ((cdr last-tag)
492 (if (not (eq? (cdr last-tag) 'string-list))
493 (syntax-error
494 "Tag :" (car last-tag) " takes string list argument"))
495 (set! opt-list (append opt-list (list (require-string-list))))
496 (set! last-tag #f))
497 (else
498 (set! state 'arg)
499 (set! arg-list (append arg-list (list (require-string-list)))))))
500 (else
501 (set! arg-list (append arg-list (list (require-string-list))))))
502 #f)
482 (else 503 (else
483 #t)) 504 #t))
484 (cons opt-list arg-list)))) 505 (cons opt-list arg-list))))
485 506
507 ;;; sieve-parse-arguments: Parse the arguments to a test or an action.
508 ;;; ENTRY is the syntax table entry to guide the parsing
509 ;;;
510 (define (sieve-parse-arguments ident entry)
511 (DEBUG 100 "sieve-parse-arguments" entry)
512 (let ((arg-list (sieve-preprocess-arguments (car (cdr entry)))))
513 ;; Process positional arguments
514 (do ((expect (car (cdr (cdr entry))) (cdr expect))
515 (argl (cdr arg-list) (cdr argl))
516 (n 1 (1+ n)))
517 ((cond
518 ((null? expect)
519 (if (not (null? argl))
520 (syntax-error
521 "Too many positional arguments for " ident
522 " (bailed out at " (car argl) ")"))
523 #t)
524 ((null? argl)
525 (if (not (null? expect))
526 (syntax-error
527 "Too few positional arguments for " ident))
528 #t)
529 (else #f)) #f)
530 (let ((expect-type (car expect))
531 (arg (car argl)))
532 (cond
533 ((and (eq? expect-type 'string-list)
534 (eq? (car arg) 'string))
535 ;; Coerce string to string-list
536 (sieve-exp-append (list 'list (cdr arg))))
537 ((eq? expect-type (car arg))
538 (if (eq? expect-type 'string-list)
539 (sieve-exp-append (append (list 'list) (cdr arg)))
540 (sieve-exp-append (cdr arg))))
541 (else
542 (syntax-error
543 "Type mismatch in argument " n " to " (cdr ident)
544 "; expected " expect-type ", but got " (car arg))))))
545 ;; Process optional arguments (tags).
546 ;; They have already been tested
547 (for-each
548 (lambda (tag)
549 (sieve-exp-append (cond
550 ((eq? (car tag) 'tag)
551 (string->symbol (string-append "#:" (cdr tag))))
552 ((eq? (car tag) 'string-list)
553 (append (list 'list) (cdr tag)))
554 (else
555 (cdr tag)))))
556 (car arg-list))))
557
486 ;;; test-list = "(" test *("," test) ")" 558 ;;; test-list = "(" test *("," test) ")"
487 (define (sieve-parse-test-list) 559 (define (sieve-parse-test-list)
488 (do ((token (sieve-parse-test) (sieve-parse-test))) 560 (do ((token (sieve-parse-test) (sieve-parse-test)))
...@@ -527,50 +599,8 @@ ...@@ -527,50 +599,8 @@
527 (if (not test) 599 (if (not test)
528 (syntax-error "Unknown test name: " (cdr ident))) 600 (syntax-error "Unknown test name: " (cdr ident)))
529 (putback-token) 601 (putback-token)
530 (let ((arg-list (sieve-parse-arguments (car (cdr test))))) 602 (sieve-exp-append (car test))
531 (sieve-exp-append (car test)) 603 (sieve-parse-arguments (cdr ident) test))))))
532 ;; Process positional arguments
533 (do ((expect (car (cdr (cdr test))) (cdr expect))
534 (argl (cdr arg-list) (cdr argl))
535 (n 1 (1+ n)))
536 ((cond
537 ((null? expect)
538 (if (not (null? argl))
539 (syntax-error
540 "Too many positional arguments for " ident
541 " (bailed out at " (car argl) ")"))
542 #t)
543 ((null? argl)
544 (if (not (null? expect))
545 (syntax-error
546 "Too few positional arguments for " ident))
547 #t)
548 (else #f)) #f)
549 (let ((expect-type (car expect))
550 (arg (car argl)))
551 (cond
552 ((and (eq? expect-type 'string-list)
553 (eq? (car arg) 'string))
554 ;; Coerce string to string-list
555 (sieve-exp-append (list 'list (cdr arg))))
556 ((eq? expect-type (car arg))
557 (if (eq? expect-type 'string-list)
558 (sieve-exp-append (append (list 'list) (cdr arg)))
559 (sieve-exp-append (cdr arg))))
560 (else
561 (syntax-error
562 "Type mismatch in argument " n " to " (cdr ident)
563 "; expected " expect-type ", but got " (car arg))))))
564 ;; Process optional arguments (tags).
565 ;; They have already been tested
566 (for-each
567 (lambda (tag)
568 (sieve-exp-append (if (eq? (car tag) 'tag)
569 (string->symbol
570 (string-append "#:" (cdr tag)))
571 (cdr tag))))
572 (car arg-list))
573 ))))))
574 (sieve-exp-finish)) 604 (sieve-exp-finish))
575 current-token) 605 current-token)
576 606
...@@ -664,46 +694,47 @@ ...@@ -664,46 +694,47 @@
664 694
665 ;;; Actions 695 ;;; Actions
666 696
667 ;;; Each entry is: (list ACTION-NAME FUNCTION ARG-LIST) 697 ;;; Each entry is: (list NAME FUNCTION OPT-ARG-LIST REQ-ARG-LIST)
668 ;;; ARG-LIST is a list of argument types 698 ;;; NAME is a string representing the action name,
699 ;;; FUNCTION is a corresponding function:
700 ;;; (define (action-foo [arg [arg...]] . opt-args)
701 ;;; notice, that its name must begin with "action-"
702 ;;; OPT-ARG-LIST is a list of optional arguments (tags),
703 ;;; REQ-ARG-LIST is a list of required (positional) arguments
669 (define sieve-action-table '()) 704 (define sieve-action-table '())
670 705
671 (define (sieve-find-action name) 706 (define (sieve-find-action name)
672 (sieve-syntax-table-lookup sieve-action-table name)) 707 (sieve-syntax-table-lookup sieve-action-table name))
673 708
674 (define (sieve-register-action name proc . arg-list) 709 (define (sieve-register-action name function req-arg-list opt-arg-list)
675 (if (not (sieve-find-action name)) 710 (cond
676 (set! sieve-action-table (append sieve-action-table 711 ((not (list? opt-arg-list))
677 (list 712 (lex-error "sieve-register-action: opt-arg-list must be a list"))
678 (append 713 ((not (list? req-arg-list))
679 (list name proc) arg-list)))))) 714 (lex-error "sieve-register-action: req-arg-list must be a list"))
715 ((not (or (eq? function #f)
716 (eq? function #t)
717 (procedure? function)))
718 (lex-error "sieve-register-action: bad type for function" function))
719 (else
720 (set! sieve-action-table
721 (append sieve-action-table
722 (list
723 (list name function opt-arg-list req-arg-list)))))))
680 724
681 (define (sieve-parse-action) 725 (define (sieve-parse-action)
682 (let* ((name (cdr current-token)) 726 (let* ((name (cdr current-token))
683 (descr (sieve-find-action name))) 727 (descr (sieve-find-action name)))
684 (cond 728 (cond
685 (descr 729 (descr
686 (if (car descr) 730 (cond
687 (sieve-exp-begin (car descr))) 731 ((car descr)
688 (do ((arg (cdr descr) (cdr arg))) 732 (sieve-exp-begin (car descr))
689 ((null? arg) #f) 733 (sieve-parse-arguments name descr)
690 (read-token) 734 (require-semicolon 'dont-read)
691 (case (car arg) 735 (sieve-exp-finish))
692 ((string) 736 (else
693 (require-string 'dont-read)) 737 (require-semicolon))))
694 ((string-list)
695 (require-string-list 'dont-read))
696 ((number)
697 (require-number 'dont-read))
698 ((tag)
699 (require-tag 'dont-read))
700 (else
701 (syntax-error "Malformed table entry for " name " :" (car arg))))
702 (if (car descr)
703 (sieve-exp-append (cdr current-token))))
704 (require-semicolon)
705 (if (car descr)
706 (sieve-exp-finish)))
707 (else 738 (else
708 (syntax-error "Unknown identifier: " name))))) 739 (syntax-error "Unknown identifier: " name)))))
709 740
...@@ -853,7 +884,7 @@ ...@@ -853,7 +884,7 @@
853 (display (string-append 884 (display (string-append
854 ";;;; A Guile mailbox parser made from " filename) port) 885 ";;;; A Guile mailbox parser made from " filename) port)
855 (newline port) 886 (newline port)
856 (display ";;;; by sieve.scm, GNU mailutils (0.0.9)" port) 887 (display ";;;; by sieve.scm, GNU %PACKAGE% %VERSION%" port)
857 (newline port) 888 (newline port)
858 889
859 (display "(define sieve-parser #f)" port) 890 (display "(define sieve-parser #f)" port)
......