|
1401 | 1401 | (parse-comma-separated s parse-eq*))
|
1402 | 1402 |
|
1403 | 1403 | ;; as above, but allows both "i=r" and "i in r"
|
| 1404 | +(define (parse-iteration-spec s) |
| 1405 | + (let ((r (parse-eq* s))) |
| 1406 | + (cond ((and (pair? r) (eq? (car r) '=)) r) |
| 1407 | + ((eq? r ':) r) |
| 1408 | + ((and (length= r 4) (eq? (car r) 'comparison) |
| 1409 | + (or (eq? (caddr r) 'in) (eq? (caddr r) '∈))) |
| 1410 | + `(= ,(cadr r) ,(cadddr r))) |
| 1411 | + (else |
| 1412 | + (error "invalid iteration specification"))))) |
| 1413 | + |
1404 | 1414 | (define (parse-comma-separated-iters s)
|
1405 | 1415 | (let loop ((ranges '()))
|
1406 |
| - (let ((r (parse-eq* s))) |
1407 |
| - (let ((r (cond ((and (pair? r) (eq? (car r) '=)) |
1408 |
| - r) |
1409 |
| - ((eq? r ':) |
1410 |
| - r) |
1411 |
| - ((and (length= r 4) (eq? (car r) 'comparison) |
1412 |
| - (or (eq? (caddr r) 'in) (eq? (caddr r) '∈))) |
1413 |
| - `(= ,(cadr r) ,(cadddr r))) |
1414 |
| - (else |
1415 |
| - (error "invalid iteration specification"))))) |
1416 |
| - (case (peek-token s) |
1417 |
| - ((#\,) (take-token s) (loop (cons r ranges))) |
1418 |
| - (else (reverse! (cons r ranges)))))))) |
| 1416 | + (let ((r (parse-iteration-spec s))) |
| 1417 | + (case (peek-token s) |
| 1418 | + ((#\,) (take-token s) (loop (cons r ranges))) |
| 1419 | + (else (reverse! (cons r ranges))))))) |
1419 | 1420 |
|
1420 | 1421 | (define (parse-space-separated-exprs s)
|
1421 | 1422 | (with-space-sensitive
|
|
1471 | 1472 | (loop (cons nxt lst)))
|
1472 | 1473 | ((eqv? c #\;) (loop (cons nxt lst)))
|
1473 | 1474 | ((eqv? c closer) (loop (cons nxt lst)))
|
| 1475 | + ((eq? c 'for) |
| 1476 | + (take-token s) |
| 1477 | + (let ((gen (parse-generator s nxt #f))) |
| 1478 | + (if (eqv? (require-token s) #\,) |
| 1479 | + (take-token s)) |
| 1480 | + (loop (cons gen lst)))) |
1474 | 1481 | ;; newline character isn't detectable here
|
1475 | 1482 | #;((eqv? c #\newline)
|
1476 | 1483 | (error "unexpected line break in argument list"))
|
|
1515 | 1522 | (define (parse-comprehension s first closer)
|
1516 | 1523 | (let ((r (parse-comma-separated-iters s)))
|
1517 | 1524 | (if (not (eqv? (require-token s) closer))
|
1518 |
| - (error (string "expected " closer)) |
| 1525 | + (error (string "expected \"" closer "\"")) |
1519 | 1526 | (take-token s))
|
1520 | 1527 | `(comprehension ,first ,@r)))
|
1521 | 1528 |
|
|
1525 | 1532 | `(dict_comprehension ,@(cdr c))
|
1526 | 1533 | (error "invalid dict comprehension"))))
|
1527 | 1534 |
|
1528 |
| -(define (parse-generator s first closer) |
1529 |
| - (let ((r (parse-comma-separated-iters s))) |
1530 |
| - (if (not (eqv? (require-token s) closer)) |
1531 |
| - (error (string "expected " closer)) |
1532 |
| - (take-token s)) |
1533 |
| - `(macrocall @generator ,first ,@r))) |
| 1535 | +(define (parse-generator s first allow-comma) |
| 1536 | + (let ((r (if allow-comma |
| 1537 | + (parse-comma-separated-iters s) |
| 1538 | + (list (parse-iteration-spec s))))) |
| 1539 | + `(generator ,first ,@r))) |
1534 | 1540 |
|
1535 | 1541 | (define (parse-matrix s first closer gotnewline)
|
1536 | 1542 | (define (fix head v) (cons head (reverse v)))
|
|
1960 | 1966 | `(tuple ,ex)
|
1961 | 1967 | ;; value in parentheses (x)
|
1962 | 1968 | ex))
|
| 1969 | + ((eq? t 'for) |
| 1970 | + (take-token s) |
| 1971 | + (let ((gen (parse-generator s ex #t))) |
| 1972 | + (if (eqv? (require-token s) #\) ) |
| 1973 | + (take-token s) |
| 1974 | + (error "expected \")\"")) |
| 1975 | + gen)) |
1963 | 1976 | (else
|
1964 | 1977 | ;; tuple (x,) (x,y) (x...) etc.
|
1965 | 1978 | (if (eqv? t #\, )
|
|
0 commit comments