permit hiding of starting rule name

hide-top-rule-name
Matthew Butterick 7 years ago
parent 4f225cc740
commit 57ba4a6f07

@ -171,48 +171,61 @@ This would be the place to check a syntax property for hiding.
(datum->syntax #f d (positions->srcloc start-pos end-pos) stx-with-original?-property)) (datum->syntax #f d (positions->srcloc start-pos end-pos) stx-with-original?-property))
(define (remove-rule-name component-stx #:splice? [splice #f]) (define (apply-name-property name-stx stxs)
;; when removing a rule name, we apply it as a syntax property to the remaining elements (for/list ([stx (in-list (syntax->list stxs))])
;; for possible later usage (aka, why throw away information) (syntax-property stx (syntax->datum name-stx) name-stx)))
(with-syntax ([(name . subcomponents) component-stx])
(define (splice-stx component-stx)
;; when splicing, we apply rule name as a syntax property to the remaining elements
(syntax-case component-stx ()
[(name . subcomponents)
(syntax-property #'name 'rule-id) ; name has not been removed (recognized by presence of 'rule-id)
(apply-name-property #'name #'subcomponents)]
[subcomponents ; name has been removed, but it is stored in 'generating-rule property
(let* ([name-datum (syntax-property #'subcomponents 'generating-rule)]
[name-stx (syntax-property #'subcomponents name-datum)])
(apply-name-property name-stx #'subcomponents))]))
(define (remove-rule-name component-stx)
(syntax-case component-stx ()
[(name . subcomponents)
(let ([name-datum (syntax->datum #'name)]) (let ([name-datum (syntax->datum #'name)])
(if splice (syntax-property
;; when splicing, returned list is a regular list, with each element having the property. (syntax-property
(map (λ(sc) (syntax-property sc name-datum #'name)) (syntax->list #'subcomponents)) (datum->syntax component-stx #'subcomponents component-stx component-stx)
;; when hiding, returned list should be a syntaxed list with the property name-datum #'name)
;; iow, basically the same as `component-stx`, minus the name 'generating-rule name-datum))]))
(syntax-property (datum->syntax component-stx #'subcomponents component-stx component-stx) name-datum #'name)))))
(define (preprocess-component-lists component-lists) (define (splice-component-lists component-lists)
; "preprocess" means splicing and rule-name-hiding where indicated ;; each `component-list` is a list that's either empty, or contains component-stx objects
(append*
;; each `component-list` is a list that's either empty, or has a single component-stx object
;; inside `component-stx` is a name followed by subcomponents ;; inside `component-stx` is a name followed by subcomponents
(append*
(for*/list ([component-list (in-list component-lists)] (for*/list ([component-list (in-list component-lists)]
[component-stx (in-list component-list)]) ; this has the effect of omitting any empty `component-list` #:unless (empty? component-list)
(list [component-stx (in-list component-list)])
(cond (if (or (eq? (syntax-property component-stx 'hide-or-splice) 'splice)
;; test splice first in case both hiding and splicing are set, for instance:
;; /rule : thing @rule
;; otherwise the hide prevents the splice from being expressed
[(or (eq? (syntax-property component-stx 'hide-or-splice) 'splice)
(syntax-property component-stx 'splice-rh-id)) (syntax-property component-stx 'splice-rh-id))
(remove-rule-name component-stx #:splice? #t)] ; spliced version is lifted out of the sublist (splice-stx component-stx) ; spliced version is lifted out of the sublist
[(eq? (syntax-property component-stx 'hide-or-splice) 'hide) (list component-stx))))) ; otherwise left inside sublist
(list (remove-rule-name component-stx))] ; hidden version still wrapped in a sublist
[else (list component-stx)])))))
;; rule-components->syntax: (U symbol false) (listof stx) ... #:srcloc (U #f (list src line column offset span)) -> stx ;; rule-components->syntax: (U symbol false) (listof stx) ... #:srcloc (U #f (list src line column offset span)) -> stx
;; Creates an stx out of the rule name and its components. ;; Creates an stx out of the rule name and its components.
;; The location information of the rule spans that of its components. ;; The location information of the rule spans that of its components.
(define (rule-components->syntax rule-name/false #:srcloc [srcloc #f] #:hide-or-splice? [hide-or-splice #f] . component-lists) (define (rule-components->syntax rule-name/false #:srcloc [srcloc #f] #:hide-or-splice? [hide-or-splice #f] . component-lists)
(define new-rule-name (datum->syntax #f rule-name/false srcloc stx-with-original?-property)) (define new-rule-name (syntax-property
(define new-rule-components (append* (preprocess-component-lists component-lists))) (datum->syntax #f rule-name/false srcloc stx-with-original?-property)
(define rule-result (cons new-rule-name new-rule-components)) 'rule-id #t))
(define rule-result (cons new-rule-name (splice-component-lists component-lists)))
(define syntaxed-rule-result (datum->syntax #f rule-result srcloc stx-with-original?-property)) (define syntaxed-rule-result (datum->syntax #f rule-result srcloc stx-with-original?-property))
;; not 'hide-or-splice-lhs-id, because this will now become a (right-hand) component in a different (left-hand) rule ;; not 'hide-or-splice-lhs-id, because this will now become
;; actual splicing happens when the parent rule is processed (with procedure above) ;; a (right-hand) component in a different (left-hand) rule
(syntax-property syntaxed-rule-result 'hide-or-splice hide-or-splice)) ;; actual splicing happens when the parent rule is processed (with `splice-component-lists`)
(syntax-property ((if (eq? hide-or-splice 'hide)
remove-rule-name
values) syntaxed-rule-result)
'hide-or-splice hide-or-splice))

@ -0,0 +1,2 @@
#lang brag
/top : "x"

@ -11,6 +11,7 @@
"test-errors.rkt" "test-errors.rkt"
"test-flatten.rkt" "test-flatten.rkt"
"test-hide-and-splice.rkt" "test-hide-and-splice.rkt"
"test-hide-top.rkt"
"test-lexer.rkt" "test-lexer.rkt"
"test-old-token.rkt" "test-old-token.rkt"
"test-parser.rkt" "test-parser.rkt"

@ -0,0 +1,8 @@
#lang racket/base
(require brag/examples/hide-top
brag/support
rackunit)
;; check that the top rule name can be cut (hidden)
(check-equal? (parse-to-datum "x") '("x"))
Loading…
Cancel
Save