[racket] Syntax-parse and error messages

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Wed Oct 13 04:41:12 EDT 2010

Hi All,

I am experimenting with syntax-parse in order to generate precise
error messages with a minimum of fuss. So far it looks very promising,
but I have a few questions.

Below I have systematically define syntax-classes for each
non-terminal in the grammar of cas-cade-e expressions.
I have used this grammar:

;;; SYNTAX
;;    <cas-cad-e>   ::= (cas-cad-e <val-expr> <case-clause> ...+)
;;    <case-clause> ::= [(<datum> ...) <then-expr> ...+]

Each syntax class is given a description, which is included in
an error message, when some expression fails to parse (and
it is expected to).

To focus on the error messages I have removed the expansion.
Below I have tried to test which error messages I got.

For  (casc)   I get the correct error message, namely
    casc: expected <cas-cad-expr> of the form (cas-cad-e <value-expr>
<case-clause> ...+) after 1 term in: (casc)

For     (casc #:foo)   I expected the error:
            "casc: expected value-expr in: #:foo"
but got  "casc: expected expr in: #:foo".
How do I make syntax-parse give the precise error?

For   (casc 3 [(4) ])  where the <then-expr> ...+ part is omitted
I get the error message:
   ; casc: repetition constraint violated in: (casc 3 ((4)))
It is of course correct that the "at least one" repitition contraint
is violated,
but how do I get syntax-parse to tell me, that it is due to a missing
<then-expr> in  a <case-clause>?



#lang racket
(require
 racket/stxparam
 (for-syntax unstable/syntax ; for generate-temporary
                     syntax/parse
                     syntax/stx))
;;; SYNTAX
;;    <cas-cad-e>   ::= (cas-cad-e <val-expr> <case-clause> ...+)
;;    <case-clause> ::= [(<datum> ...) <then-expr> ...+]

(define-syntax-parameter break
  (λ (stx) (raise-syntax-error 'break "The keywork break was used of
context." stx)))

(define-syntax (casc stx)
  (define-syntax-class datum
    #:attributes (d)
    #:description "<datum> part of the literal list in a <case-clause>"
    (pattern d:expr))
  (define-syntax-class then-expr
    #:attributes (e)
    #:description "an expression part to be part of a <case-clause>"
    (pattern e:expr))
  (define-syntax-class case-clause
    #:attributes ((d 1) (te 1))
    #:description "<case-clause> of the form [(<datum> ...) <then-expr> ...+"
    (pattern [(d:datum ...) te:then-expr ...+]))
  (define-syntax-class value-expr
    #:attributes (e)
    #:description "value-expr"
    (pattern e:expr))
  (define-syntax-class cas-cad-expr
    #:attributes (ve (c 1) last-c)
    #:description "<cas-cad-expr> of the form (cas-cad-e <value-expr>
<case-clause> ...+)"
    (pattern (_ ve:value-expr c:case-clause ... last-c:case-clause)))
  (syntax-parse stx
    [usage:cas-cad-expr
     #'42]))

;; Expressions that must signal an error

(casc) ; correct error message
;(casc #:foo)  ; I expected the error:  "casc: expected value-expr
..." but got "expected expr ..."
;(casc 3 [(4) ])  ; casc: repetition constraint violated in: (casc 3 ((4)))
;(casc 3 [(4) 2 3] [3])    ; only 3 is red  shouldn't that be [3] ?


;; And a legal expression
(casc 3
      [(1) 'one]
      [(3) 'three])

--
Jens Axel Søgaard


Posted on the users mailing list.