From 4fc52153b366aae911eede7c404c24b0e74ab604 Mon Sep 17 00:00:00 2001
Message-Id: <4fc52153b366aae911eede7c404c24b0e74ab604.1717245960.git.mdw@distorted.org.uk>
From: Mark Wooding <mdw@chiark.greenend.org.uk>
Date: Tue, 5 Jan 2016 17:05:59 +0000
Subject: [PATCH] src/module-parse.lisp: Support multi-word item names in
 fragment syntax.
Organization: Straylight/Edgeware

From: Mark Wooding <mdw@distorted.org.uk>

A sequence of identifiers can be written in parentheses.  There's still
no way to refer to items whose names contain objects such as classes or
methods.  This probably isn't too disastrous.
---
 doc/syntax.tex        | 21 ++++++++++++---------
 src/module-parse.lisp | 20 +++++++++++++-------
 src/sod-module.5      | 10 +++++++++-
 3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/doc/syntax.tex b/doc/syntax.tex
index aff02ab..a9dd695 100644
--- a/doc/syntax.tex
+++ b/doc/syntax.tex
@@ -353,12 +353,14 @@ declarations instead.
 
 \begin{grammar}
 <code-definition> ::=
-  "code" <identifier> ":" <identifier> @[<constraints>@]
+  "code" <identifier> ":" <item-name> @[<constraints>@]
   "{" <c-fragment> "}"
 
 <constraints> ::= "[" <list>$[\mbox{@<constraint>}]$ "]"
 
-<constraint> ::= @<identifier>^+
+<constraint> ::= @<item-name>^+
+
+<item-name> ::= <identifier> @! "(" @<identifier>^+ ")"
 \end{grammar}
 
 The @<c-fragment> will be output unchanged to one of the output files.
@@ -367,18 +369,19 @@ The first @<identifier> is the symbolic name of an output file.  Predefined
 output file names are @"c" and @"h", which are the implementation code and
 header file respectively; other output files can be defined by extensions.
 
-The second @<identifier> provides a name for the output item.  Several C
-fragments can have the same name: they will be concatenated together in the
-order in which they were encountered.
+Output items are named with a sequence of identifiers, separated by
+whitespace, and enclosed in parentheses.  As an abbreviation, a name
+consisting of a single identifier may be written as just that identifier,
+without the parentheses.
 
 The @<constraints> provide a means for specifying where in the output file
 the output item should appear.  (Note the two kinds of square brackets shown
 in the syntax: square brackets must appear around the constraints if they are
 present, but that they may be omitted.)  Each comma-separated @<constraint>
-is a sequence of identifiers naming output items, and indicates that the
-output items must appear in the order given -- though the translator is free
-to insert additional items in between them.  (The particular output items
-needn't be defined already -- indeed, they needn't be defined ever.)
+is a sequence of names of output items, and indicates that the output items
+must appear in the order given -- though the translator is free to insert
+additional items in between them.  (The particular output items needn't be
+defined already -- indeed, they needn't be defined ever.)
 
 There is a predefined output item @"includes" in both the @"c" and @"h"
 output files which is a suitable place for inserting @"\#include"
diff --git a/src/module-parse.lisp b/src/module-parse.lisp
index 8022bbf..9522085 100644
--- a/src/module-parse.lisp
+++ b/src/module-parse.lisp
@@ -48,22 +48,28 @@ (define-pluggable-parser module typename (scanner pset)
 ;;; Fragments.
 
 (define-pluggable-parser module code (scanner pset)
-  ;; `code' id `:' id [constraints] `{' c-fragment `}'
+  ;; `code' id `:' item-name [constraints] `{' c-fragment `}'
   ;;
   ;; constrains ::= `[' constraint-list `]'
-  ;; constraint ::= id+
+  ;; constraint ::= item-name+
+  ;; item-name ::= id | `(' id+ `)'
   (declare (ignore pset))
   (with-parser-context (token-scanner-context :scanner scanner)
-    (flet ((kw ()
-	     (parse (seq ((kw :id))
-		      (intern (frob-identifier kw) 'keyword)))))
+    (labels ((kw ()
+	       (parse (seq ((kw :id))
+			(intern (frob-identifier kw) 'keyword))))
+	     (item ()
+	       (parse (or (kw)
+			  (seq (#\( (names (list (:min 1) (kw))) #\))
+			    names)))))
       (parse (seq ("code"
 		   (reason (kw))
 		   #\:
-		   (name (kw))
+		   (name (item))
 		   (constraints (? (seq (#\[
 					 (constraints (list (:min 1)
-							(list (:min 1) (kw))
+							(list (:min 1)
+							  (item))
 							#\,))
 					 #\])
 				     constraints)))
diff --git a/src/sod-module.5 b/src/sod-module.5
index 9779822..236629a 100644
--- a/src/sod-module.5
+++ b/src/sod-module.5
@@ -480,7 +480,7 @@ any character other than newline
 .B code
 .I identifier
 .B
-.I identifier
+.I item-name
 .RI [ constraints ]
 .B {
 .I c-fragment
@@ -494,7 +494,15 @@ any character other than newline
 .br
 .I constraint
 ::=
+.IR item-name \*+
+.br
+.I item-name
+::=
+.I identifier
+|
+.B (
 .IR identifier \*+
+.B )
 .
 .SS Class definitions
 .I
-- 
[mdw]

