@(name file) @;; @;; Check syntax block after function @;; @(define check-synb ()) .synb @ (assert bad ln `bad .synb block`) @ (repeat :gap 0 :min 1) .mets @(skip) @ (maybe) @ (repeat :gap 0 :mintimes 1) .mets \ \ @(skip) @ (last :mandatory) @ (trailer) .mets @(skip) @ (end) @ (end) @ (last :mandatory) .syne @ (end) @ (assert bad ln `missing .desc`) .desc @ (assert bad ln `blank line after .desc`) @/..*/ @(end) @;; @;; Check variable description headings @;; @(define check-var ()) @ (cases) @; exception .coNP @/Variables|Special variables/ @@, s-ifmt @(skip) @ (or) @; exception .coNP @/Variables|Special variables/ @@, *0 @(skip) @ (or) .coNP @/Variables|Special variables/@(assert bad ln `bad Variables heading`)@(rep :gap 0) @@, @{x /\S+/}@(last :mandatory) @@ @y and @@ @{z /\S+/}@(end) @ (assert bad ln `no .desc after variables heading`) .desc @ (or) .coNP @/Variable|Special variable/@(assert bad ln `bad Variable heading`) @{x /\S+/} @ (assert bad ln `no .desc after variable heading`) .desc @ (end) @(end) @;; @;; Check function/macro/operator headings @;; @(define check-func ()) @ (cases) .coNP @{type /Operator|Macro/}/function @(skip) @ (assert bad ln `no .synb after @type/function heading`) @ (check-synb) @ (or) .coNP Operator @@ @op and macro @@ @mac @ (assert bad ln `no .synb after Operator and macro heading`) @ (check-synb) @ (or) .coNP @{type /Function|Operator|Macro|Accessor|Method|Structure|Pattern operator|(Operators|Macros)\/function/}s@(assert bad ln `bad @{type}s heading`)@(rep :gap 0) @@, @{x /\S+/}@(last :mandatory) @@ @y and @@ @{z /\S+/}@(end) @ (assert bad ln `no .synb after @{type}s heading`) @ (check-synb) @ (or) .coNP @{type /Function|Operator|Macro|Accessor|Method|Structure|Pattern operator|Parameter list macro/}@(assert bad ln `bad @type heading`) @@ @{x /\S+/}@junk @ (assert bad ln `extra elements in singular @type heading`) @ (bind junk "") @ (assert bad ln `no .synb after @type heading`) @ (check-synb) @ (end) @(end) @;; @;; check .code, .codn, .cod2, .cod3, .meta and .metn. @;; @(define check-code ()) @ (cases) .@{type /code|meta/} "@(assert bad ln `.@type needs one argument`)@x"@(eol) @ (or) .@{type /code|meta/}@(assert bad ln `.@type needs one argument`) @{x /\S+/}@(eol) @ (or) .cod3 @(assert bad ln `.cod3 needs three arguments`)@x @y @{z /\S+/}@(eol) @ (or) .@{type /codn|cod2|metn/} @(assert bad ln `.@type needs two arguments`)@(cases)"@x"@(or)@{x /\S+/}@(end) @{y /\S+/}@(eol) @ (assert bad ln `.codn second argument doesn't begin with punctuation`) @ (require (or (not (memqual type '("codn" "metn"))) (chr-ispunct [y 0]))) @ (end) @(end) @;; @;; Check .mono/.onom pairing @;; @(define check-mono ()) .mono @ (assert bad ln `.mono not closed`) @ (repeat :gap 0) @ (none) .mono @ (end) @ (last :mandatory) .onom @ (end) @(end) @;; @;; Check .verb/.brev pairing @;; @(define check-verb ()) .verb @ (assert bad ln `.verb not closed`) @ (repeat :gap 0) @ (none) .verb @ (end) @ (last :mandatory) .brev @ (end) @(end) @;; @;; Check for various dangling @;; macros. @;; @(define check-spurious ()) @ {mac /.(cble|syne)/}@(skip) @ (throw bad ln `dangling @mac`) @(end) @;; @;; Main @;; @(bind errors 0) @(repeat) @ (line ln) @ (try) @ (cases) @ (check-var) @ (or) @ (check-func) @ (or) @ (check-code) @ (or) @ (check-verb) @ (or) @ (check-mono) @ (or) @ (check-synb) @ (or) @ (check-spurious) @ (end) @ (catch bad (line msg)) @ (do (inc errors) (put-line `@file:@line:@msg`)) @ (end) @(end) @(do (exit (zerop errors)))