[chatter] r11800 - in trunk/sandbox/dydoc: . internal-rep markup-parser markup-translator support topic-resolver

agent at mccarthy.opendylan.org agent at mccarthy.opendylan.org
Fri May 9 04:06:21 CEST 2008


Author: agent
Date: Fri May  9 04:06:20 2008
New Revision: 11800

Added:
   trunk/sandbox/dydoc/markup-translator/content-processing.dylan   (contents, props changed)
   trunk/sandbox/dydoc/markup-translator/topic-processing.dylan   (contents, props changed)
Modified:
   trunk/sandbox/dydoc/dydoc.lid
   trunk/sandbox/dydoc/internal-rep/body-elements.dylan
   trunk/sandbox/dydoc/internal-rep/helpers.dylan
   trunk/sandbox/dydoc/internal-rep/misc-elements.dylan
   trunk/sandbox/dydoc/internal-rep/module.dylan
   trunk/sandbox/dydoc/internal-rep/printers.dylan
   trunk/sandbox/dydoc/internal-rep/quote-elements.dylan
   trunk/sandbox/dydoc/internal-rep/toc-nav-elements.dylan
   trunk/sandbox/dydoc/internal-rep/topic-elements.dylan
   trunk/sandbox/dydoc/markup-parser/grammar.txt
   trunk/sandbox/dydoc/markup-parser/markup-parser.dylan
   trunk/sandbox/dydoc/markup-translator/check-helpers.dylan
   trunk/sandbox/dydoc/markup-translator/module.dylan
   trunk/sandbox/dydoc/support/common.dylan
   trunk/sandbox/dydoc/topic-resolver/resolving.dylan
   trunk/sandbox/dydoc/topic-resolver/visitors.dylan
Log:
Job: minor
This one compiles.


Modified: trunk/sandbox/dydoc/dydoc.lid
==============================================================================
--- trunk/sandbox/dydoc/dydoc.lid	(original)
+++ trunk/sandbox/dydoc/dydoc.lid	Fri May  9 04:06:20 2008
@@ -26,7 +26,8 @@
             markup-parser/rule-tokenizers
             markup-translator/module
             markup-translator/check-helpers
-            markup-translator/token-processing
+            markup-translator/topic-processing
+            markup-translator/content-processing
             topic-resolver/module
             topic-resolver/arranging
             topic-resolver/merging

Modified: trunk/sandbox/dydoc/internal-rep/body-elements.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/body-elements.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/body-elements.dylan	Fri May  9 04:06:20 2008
@@ -9,37 +9,61 @@
 ///   api-ref        - Basically converts to an API qv.
 ///   marker-ref     - An <xref> to a <footnote> or <ph-marker>.
 ///   synopsis-ref   - <conref> with the #"title" or #"shortdesc" style.
-define constant <markup-deque> = limited(<deque>,
+///
+define constant <markup-seq> = limited(<stretchy-vector>,
       of: type-union(<string>, <character>, <inline-image>, <html-content>,
-                     <dita-content>, <conref>, <xref>, <toc-xref>, <api-name>,
-                     <parm-name>, <term>, <term-style>, <code-phrase>, <entity>,
-                     <cite>, <bold>, <italic>, <underline>, <emphasis>));
+                     <dita-content>, <conref>, <xref>, <api-name>,
+                     <parm-name>, <term>, <term-style>, <code-phrase>,
+                     <entity>, <cite>, <bold>, <italic>, <underline>,
+                     <emphasis>));
+                     
+/// Synopsis: List of elements corresponding to lines-content grammar.
+///   marginal-code-block  - <code-block>
+///   marginal-verbatim-block - <pre>
+///   figure-ref-line      - <fig>
+///   content-ref-line     - <conref> with the #"toc" style.
+///   ditto-ref-line       - <ditto-placeholder>
+///   api-list-ref-line    - <api-list-placeholder>
+///   bracketed-raw-block  - <code-block> or <pre>
+///   table                - <simple-table>
+///   bullet-list          - <unordered-list>
+///   numeric-list         - <ordered-list>
+///   hyphenated-list      - <one-line-defn-list>
+///   phrase-list          - <two-line-defn-list>
+///   paragraph            - <paragraph>
+///
+define constant <content-seq> = limited(<stretchy-vector>,
+   of: type-union(<code-block>, <pre>, <fig>, <conref>, <ditto-placeholder>,
+                  <api-list-placeholder>, <simple-table>, <unordered-list>,
+                  <ordered-list>, <defn-list>, <paragraph>));
 
 define class <section> (<interm-element>)
-   slot id :: false-or(<string>);
-   slot title = make(<title-deque>);
-   slot content = make(<deque>);
+   slot id :: false-or(<string>) = #f;
+   slot title = make(<title-seq>);
+   slot content = make(<content-seq>);
 end class;
 
 define class <footnote> (<interm-element>)
-   slot number;
-   slot content = make(<deque>);
+   slot index :: type-union(<character>, <integer>), init-keyword: #"index";
+   slot content = make(<content-seq>);
 end class;
 
 define class <paragraph> (<interm-element>)
-   slot content = make(<markup-deque>);
+   slot content = make(<markup-seq>);
 end class;
 
 define class <note> (<interm-element>)
-   slot content;
+   slot content = make(<content-seq>);
 end class;
 
 define class <warning-note> (<note>)
 end class;
 
 define class <conref> (<interm-element>)
-   slot target :: type-union(<topic>, <target-placeholder>);
-   slot style :: one-of(#"title", #"shortdesc", #"toc");
+   slot target :: type-union(<topic>, <target-placeholder>),
+      init-keyword: #"target";
+   slot style :: one-of(#"title", #"shortdesc", #"toc"),
+      init-keyword: #"style";
 end class;
 
 /// This will be rendered as an empty DITA <ph> or HTML anchor. Technically,
@@ -47,22 +71,21 @@
 /// Don't want to include content in the tag in case DITA processors won't consider
 /// it as code in a code block.
 define class <ph-marker> (<interm-element>)
-   slot index :: false-or(type-union(<integer>, <character>)),
-         init-keyword: #"index";
+   slot index :: type-union(<integer>, <character>), init-keyword: #"index";
 end class;
 
 define class <ordered-list> (<interm-element>)
-   slot style :: one-of(#"num", #"alpha");
-   slot start :: <integer> = 1;
-   slot items;
+   slot start :: type-union(<integer>, <character>), init-keyword: #"start";
+   slot items :: <vector> /* of <content-seq> */;
 end class;
 
 define class <unordered-list> (<interm-element>)
-   slot items;
+   slot items :: <vector> /* of <content-seq> */;
 end class;
 
 define class <defn-list> (<interm-element>)
-   slot items :: <array>;
+   slot items :: <array> /* 2-by-n, first col of <markup-seq>,
+                            second col of <content-seq> */;
 end class;
 
 define class <one-line-defn-list> (<defn-list>)
@@ -72,30 +95,37 @@
 end class;
 
 define class <fig> (<interm-element>)
-   slot image;
-   slot abs-size :: false-or(<integer>);
-   slot rel-size :: false-or(<integer>);
+   slot image-name :: <string>;
+   slot abs-size :: false-or(<integer>) = #f;
+   slot rel-size :: false-or(<integer>) = #f;
    slot title :: <string>;
 end class;
 
 define class <inline-image> (<interm-element>)
-   slot image, init-keyword: #"image";
+   slot image-name :: <string>, init-keyword: #"image";
    slot alt-text :: <string>, init-keyword: #"alt-text";
 end class;
 
 define class <pre> (<interm-element>)
-   slot content;
+   slot content = make(<stretchy-vector>) /* of <string>, <ph-marker> */;
 end class;
 
 define class <simple-table> (<interm-element>)
-   slot headings;
+   slot headings :: <vector>;
    slot items :: <array>;
 end class;
 
 define class <code-block> (<pre>)
 end class;
 
-define class <parm-list> (<defn-list>)
+/// Mixin class for <defn-list> indicating an argument or value list.
+define class <parm-list> (<object>)
+end class;
+
+define class <one-line-parm-list> (<one-line-defn-list>, <parm-list>)
+end class;
+
+define class <two-line-parm-list> (<two-line-defn-list>, <parm-list>)
 end class;
 
 define class <html-content> (<interm-element>)

Modified: trunk/sandbox/dydoc/internal-rep/helpers.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/helpers.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/helpers.dylan	Fri May  9 04:06:20 2008
@@ -21,8 +21,8 @@
 
 /// Synopsis: Converts a title to a string. This can be done without resolving
 /// anything.
-define method stringify-title (title :: <title>) => (title :: <string>)
-   stringify-title-part(title.content)
+define method stringify-title (title :: <title-seq>) => (title :: <string>)
+   stringify-title-part(title)
 end method;
 
 define method stringify-title-part (string :: <string>) => (string :: <string>)
@@ -34,7 +34,7 @@
 end method;
 
 define method stringify-title-part (img :: <inline-image>) => (string :: <string>)
-   img.alt-text | "[img]"
+   concatenate("[", img.alt-text | "img", "]")
 end method;
 
 define method stringify-title-part

Modified: trunk/sandbox/dydoc/internal-rep/misc-elements.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/misc-elements.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/misc-elements.dylan	Fri May  9 04:06:20 2008
@@ -1,10 +1,9 @@
 module: internal-rep
 synopsis: Placeholders that are replaced by actual elements after all is read.
 
+/// Subclasses of <interm-element> have slots, but these are not initialized.
 define class <interm-element> (<object>)
-   // False for topics; topics' parents are indicated by parent slot.
-   slot element-owner :: false-or(<interm-element>), init-keyword: #"owner";
-   slot element-source = #f;
+   slot element-source = #f; // TODO: Make mandatory keyword.
 end class;
 
 /// Synopsis: Used when the target is unknown. May generally refer to a topic,
@@ -24,5 +23,14 @@
 end class;
 
 define class <ditto-placeholder> (<interm-element>)
-   slot target :: type-union(<topic>, <target-placeholder>);
+   slot target :: type-union(<topic>, <target-placeholder>),
+      init-keyword: #"target";
+end class;
+
+define class <marker-placeholder> (<interm-element>)
+   slot index :: type-union(<integer>, <character>), init-keyword: #"index";
+end class;
+
+/// Synopsis: Placeholder for contents of current topic, i.e. "[CONTENTS]".
+define class <toc-placeholder> (<interm-element>)
 end class;

Modified: trunk/sandbox/dydoc/internal-rep/module.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/module.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/module.dylan	Fri May  9 04:06:20 2008
@@ -11,24 +11,27 @@
    export
       <api-doc>, <api-list-placeholder>, <api-name>, <bold>, <cite>,
       <class-doc>, <code-block>, <code-phrase>, <con-topic>, <conref>,
-      <defn-list>, <dita-content>, <ditto-placeholder>, <emphasis>, <entity>,
-      <fig>, <footnote>, <function-doc>, <generic-doc>, <html-content>,
-      <inline-image>, <interm-element>, <italic>, <library-doc>, <macro-doc>,
+      <content-seq>, <defn-list>, <dita-content>, <ditto-placeholder>,
+      <emphasis>, <entity>, <fig>, <footnote>, <function-doc>, <generic-doc>,
+      <html-content>, <inline-image>, <interm-element>, <italic>,
+      <library-doc>, <macro-doc>, <marker-placeholder>, <markup-seq>,
       <module-doc>, <note>, <one-line-defn-list>, <ordered-list>, <paragraph>,
       <parm-list>, <parm-name>, <ph-marker>, <pre>, <ref-topic>, <section>,
       <simple-table>, <slot-doc>, <target-placeholder>, <term-style>, <term>,
-      <title>, <toc-xref>, <topic-ref>, <topic>, <two-line-defn-list>,
-      <underline>, <unordered-list>, <variable-doc>, <warning-note>, <xref>;
+      <title-seq>, <toc-placeholder>, <toc-xref>, <topic-ref>, <topic>,
+      <topic-content-seq>, <two-line-defn-list>, <underline>,
+      <unordered-list>, <variable-doc>, <warning-note>, <xref>;
 
    export
-      args-section, args-section-setter, conds-section, conds-section-setter,
-      content, content-setter, element-owner, element-owner-setter,
-      element-source, headings, headings-setter, id, id-setter, items,
-      items-setter, keywords-section, keywords-section-setter, parent,
-      parent-setter, relevant-to, see-also, see-also-section,
-      see-also-section-setter, shortdesc, shortdesc-setter, target,
-      target-setter, text, text-setter, title, title-setter, vals-section,
-      vals-section-setter;
+      abs-size, abs-size-setter, args-section, args-section-setter,
+      conds-section, conds-section-setter, content, content-setter,
+      element-source, headings, headings-setter, id, id-setter, image-name,
+      image-name-setter, items, items-setter, keywords-section,
+      keywords-section-setter, parent, parent-setter, rel-size,
+      rel-size-setter, relevant-to, relevant-to-setter, see-also,
+      see-also-setter, see-also-section, see-also-section-setter, shortdesc,
+      shortdesc-setter, target, target-setter, text, text-setter, title,
+      title-setter, vals-section, vals-section-setter;
 
    export
       <topic-level-style>, stringify-title;

Modified: trunk/sandbox/dydoc/internal-rep/printers.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/printers.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/printers.dylan	Fri May  9 04:06:20 2008
@@ -5,8 +5,11 @@
           o.title, o.id, o.parent, o.content);
 end method;
 
-define method print-object (o :: <title>, s :: <stream>) => ()
-   print-object(o.content, s);
+define method print-object
+   (o :: type-union(<title-seq>, <markup-seq>, <content-seq>, <topic-content-seq>),
+    s :: <stream>)
+=> ()
+   print-object(as(<stretchy-vector>, o), s);
 end method;
 
 define method print-object (o :: <paragraph>, s :: <stream>) => ()

Modified: trunk/sandbox/dydoc/internal-rep/quote-elements.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/quote-elements.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/quote-elements.dylan	Fri May  9 04:06:20 2008
@@ -5,11 +5,12 @@
 define class <xref> (<interm-element>)
    // If the target is <topic>, <footnote>, <ph-marker>, or <section>, the DITA
    // xref tag will have a format attr of "dita," else based on the URL; the 
-   // scope attr will be "local," else "external."
+   // scope attr will be "local," else "external." If the text is <conref>,
+   // its style must be #"title" and the target's title is used as the text.
    slot target :: type-union(<topic>, <footnote>, <section>, <ph-marker>, <url>,
-                             <target-placeholder>),
+                             <target-placeholder>, <marker-placeholder>),
          init-keyword: #"target";
-   slot text :: type-union(<api-name>, <parm-name>, <string>),
+   slot text :: type-union(<api-name>, <parm-name>, <string>, <conref>),
          init-keyword: #"text";
 end class;
 

Modified: trunk/sandbox/dydoc/internal-rep/toc-nav-elements.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/toc-nav-elements.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/toc-nav-elements.dylan	Fri May  9 04:06:20 2008
@@ -4,11 +4,11 @@
 define class <toc-map> (<object>)
    slot title :: <string>;
    slot shortdesc;
-   constant slot authors = make(<stretchy-vector>);
+   slot authors :: <stretchy-vector>;
 end class;
 
 define class <topic-ref> (<object>)
    slot navtitle :: <string>;
    slot target :: false-or(type-union(<topic>, <url>, <target-placeholder>));
-   slot automatic-default? :: <boolean> = #f;
+   slot automatic-default? :: <boolean>, required-init-keyword: #"auto";
 end class;

Modified: trunk/sandbox/dydoc/internal-rep/topic-elements.dylan
==============================================================================
--- trunk/sandbox/dydoc/internal-rep/topic-elements.dylan	(original)
+++ trunk/sandbox/dydoc/internal-rep/topic-elements.dylan	Fri May  9 04:06:20 2008
@@ -5,35 +5,50 @@
 ///   text           - <string> and <character>
 ///   image-ref      - <inline-image>
 ///   quote          - <bold>, etc., but not <xref>, <toc-xref>, <api-name>,
-///                    or <parm-name> which are introducted by qv and toc.
+///                    or <parm-name> which are introduced by qv and toc.
 ///   bracketed-render-block  - <dita-content> or <html-content>
-define constant <title-deque> = limited(<deque>,
+///
+define constant <title-seq> = limited(<stretchy-vector>,
       of: type-union(<string>, <character>, <inline-image>, <html-content>,
                      <dita-content>, <term>, <term-style>, <code-phrase>, <entity>,
                      <cite>, <bold>, <italic>, <underline>, <emphasis>));
+                     
+/// Synopsis: List of elements corresponding to topic-content grammar.
+///   titled-topic         - <section> for section level titled-topic.
+///   indented-directive   - <note> or <warning-note>
+///   flush-content        - As in <content-deque>
+///   footnote             - <footnote>
+///
+define constant <topic-content-seq> = limited(<stretchy-vector>,
+   of: type-union(<code-block>, <pre>, <fig>, <conref>, <ditto-placeholder>,
+                  <api-list-placeholder>, <simple-table>, <unordered-list>,
+                  <ordered-list>, <defn-list>, <paragraph>, <note>, <section>,
+                  <footnote>));
 
 define class <topic> (<interm-element>)
    // No placeholder needed for fixed-parent, because the parent is known from
    // topic nesting markup.
    slot fixed-parent :: false-or(<topic>) = #f;
+   
    // parent is parent topic as indicated by "Section:" directive. If not false,
    // should end up being the same as fixed-parent (if fixed-parent is not false).
    // If not, caught during placeholder resolution.
    slot parent :: false-or(type-union(<topic>, <target-placeholder>)) = #f;
-   slot id :: false-or(<string>) = #f;
-   slot title :: <title>;
+   
+   slot id :: false-or(<string>) = #f,
+         init-keyword: #"id";
+         
+   slot title = make(<title-seq>);
    slot shortdesc :: false-or(<paragraph>) = #f;
-   slot content :: false-or(<markup>) = #f;
-   slot see-also = make(<deque>) /* of <topic>, <url>, or <target-placeholder> */;
-   slot relevant-to = make(<deque>) /* of <topic> or <target-placeholder> */;
+   slot content = make(<topic-content-seq>);
+   
+   slot see-also = make(<stretchy-vector>) /* of <topic>, <url>, or <target-placeholder> */;
+   slot relevant-to = make(<stretchy-vector>) /* of <topic> or <target-placeholder> */;
+
    // see-also-section is filled in later after all see-alsos are resolved.
    slot see-also-section :: false-or(<section>) = #f;
 end class;
 
-define class <title> (<interm-element>)
-   slot content :: <sequence> = make(<deque>);
-end class;
-
 define class <ref-topic> (<topic>)
 end class;
 

Modified: trunk/sandbox/dydoc/markup-parser/grammar.txt
==============================================================================
--- trunk/sandbox/dydoc/markup-parser/grammar.txt	(original)
+++ trunk/sandbox/dydoc/markup-parser/grammar.txt	Fri May  9 04:06:20 2008
@@ -81,9 +81,9 @@
 line-content: 
   !eos !topic-directive-spec !topic-title !section-directive !footnote
   ( blank-lines / marginal-code-block / marginal-verbatim-block /
-  figure-ref-line / content-ref-line / ditto-ref-line / bracketed-raw-block /
-  table / bullet-list / numeric-list / hyphenated-list / phrase-list /
-  paragraph )
+  figure-ref-line / content-ref-line / ditto-ref-line / api-list-ref-line /
+  bracketed-raw-block / table / bullet-list / numeric-list / hyphenated-list /
+  phrase-list / paragraph )
 paragraph:
   paragraph-line+
 paragraph-til-null-directive:

Modified: trunk/sandbox/dydoc/markup-parser/markup-parser.dylan
==============================================================================
--- trunk/sandbox/dydoc/markup-parser/markup-parser.dylan	(original)
+++ trunk/sandbox/dydoc/markup-parser/markup-parser.dylan	Fri May  9 04:06:20 2008
@@ -24,7 +24,10 @@
    let context = make(<markup-context>);
    let markup-block-contents = parse-markup-block(text, context);
    log-object("Markup", markup-block-contents);
-   visit-token-sources(markup-block-contents, rcurry(token-source-setter, text));
+   visit-token-sources(markup-block-contents,
+                       method (tok :: <token-source>) => ()
+                          tok.token-source := text;
+                       end);
    markup-block-contents
 end method;
 

Modified: trunk/sandbox/dydoc/markup-translator/check-helpers.dylan
==============================================================================
--- trunk/sandbox/dydoc/markup-translator/check-helpers.dylan	(original)
+++ trunk/sandbox/dydoc/markup-translator/check-helpers.dylan	Fri May  9 04:06:20 2008
@@ -2,14 +2,6 @@
 synopsis: Code to integrate sections and intermediate objects into the greater whole.
 
 
-/// Synopsis: References to markers that have yet to be assigned. Scope limited
-/// to a file/comment block.
-/// Discussion: This table contains actual <ph-marker> instances, but their
-/// owners are not defined. When the marker is placed, it is not made anew, but
-/// rather retrieved from this table and its owner set.
-define constant $block-markers = make(<object-table>);
-
-
 /// IDs can have any character except space, "/", "[", "]".
 define inline method check-topic-id (id :: <string>) => ()
    when (member?(' ', id) | member?('/', id) | member?('[', id) | member?(']', id))
@@ -25,7 +17,7 @@
 /// Titles (in string form) cannot have leading colon. I say string form,
 /// because that is the one used in links, and this restriction is to avoid
 /// ambuiguous links.
-define inline method check-topic-title (title :: <title>) => ()
+define inline method check-topic-title (title :: <title-seq>) => ()
    when (title.stringify-title.first = ':')
       error("Title cannot have leading colon.")
    end when;
@@ -36,14 +28,15 @@
 /// is used to check within a single topic; this is also checked across multiple
 /// topics when merging [TODO].
 define inline method check-no-shortdesc (topic :: <topic>) => ()
-   when (slot-initialized?(topic, shortdesc))
+   when (topic.shortdesc)
       error("Only one synopsis in a topic.")
    end when;
 end method;
 
 
 define method check-quote-specifiers
-   (quote :: <quote-token>, default-specs :: <table>, #key for-title) => ()
+   (quote :: <quote-token>, default-specs :: <table>, #key for-title)
+=> (specs :: <sequence>)
    let specs = remove-duplicates(
          if (quote.quote-spec.empty?)
             default-specs[quote.open-quote]
@@ -61,7 +54,8 @@
       error("Titles can't have qv or toc specifiers.")
    end when;
 
-   // A quote can basically be a qv/toc, bib, or term. Former trumps latter.
+   // A quote can basically be a qv/toc, bib, or term. The other stuff is
+   // decorative. Former trumps latter.
    when (member?(#"qv", specs) | member?(#"toc", specs))
       specs := remove!(specs, #"bib");
       specs := remove!(specs, #"term");
@@ -69,6 +63,7 @@
    when (member?(#"bib", specs))
       specs := remove!(specs, #"term");
    end when;
+   specs;
 end method;
 
 
@@ -138,15 +133,3 @@
                     over: token.ascii-overline?);
    style ~= $section-style
 end method;
-
-
-//
-//
-//
-
-
-define method ensure-marker (index :: type-union(<character>, <integer>))
-=> (marker :: <ph-marker>)
-   element($block-markers, index, default: #f) | 
-         ($block-markers[index] := make(<ph-marker>, index: index))
-end method;

Added: trunk/sandbox/dydoc/markup-translator/content-processing.dylan
==============================================================================
--- (empty file)
+++ trunk/sandbox/dydoc/markup-translator/content-processing.dylan	Fri May  9 04:06:20 2008
@@ -0,0 +1,327 @@
+module: markup-translator
+
+//
+// process-tokens for <topic-content-seq> or <content-seq>
+//
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <marginal-code-block-token>)
+=> ()
+   let code-block = make(<code-block>);
+   process-tokens(code-block, token.token-content);
+   add!(seq, code-block);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <marginal-verbatim-block-token>)
+=> ()
+   let verb-block = make(<pre>);
+   process-tokens(verb-block, token.token-content);
+   add!(seq, verb-block);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <figure-ref-line-token>)
+=> ()
+   let fig = make(<fig>);
+   fig.image-name := token.filename;
+   fig.title := token.caption;
+   select (token.scale-factor.object-class)
+      <perc-scale-token> => fig.rel-size := token.scale-factor.factor;
+      <mult-scale-token> => fig.abs-size := token.scale-factor.factor;
+   end select;
+   add!(seq, fig);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <content-ref-line-token>)
+=> ()
+   let ref = if (token.link)
+                let targ = make(<target-placeholder>, link: token.link);
+                make(<conref>, style: #"toc", target: targ);
+             else
+                make(<toc-placeholder>);
+             end if;
+   add!(seq, ref);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <ditto-ref-line-token>)
+=> ()
+   add!(seq, make(<ditto-placeholder>, target: token.link));
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <api-list-ref-line-token>)
+=> ()
+   // TODO
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <bracketed-raw-block-token>)
+=> ()
+   let raw-block =
+         make(if (token.block-type = #"verbatim") <pre> else <code-block> end);
+   process-tokens(raw-block, token.token-content);
+   add!(seq, raw-block);
+end method;
+
+
+// define method process-tokens
+//    (seq :: type-union(<topic-content-seq>, <content-seq>),
+//     token :: <table-token>)
+// => ()
+//    let simp-tbl = make(<simple-table>);
+//    // TODO
+// end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: type-union(<numeric-list-token>, <bullet-list-token>))
+=> ()
+   // <x-list-token> contains
+   //   <x-list-first-item-token> or <x-list-item-token> contains
+   //     <content-seq>
+   let token-items-content = map(token-content, token.token-content);
+   let list =
+         select (token.object-class)
+            <numeric-list-token> => make(<ordered-list>, start: token.list-start);
+            <bullet-list-token> => make(<unordered-list>);
+         end select;
+   list.items = make(<vector>, size: token-items-content.size);
+   for (i from 0, token-item-content in token-items-content)
+      let list-item-content = make(<content-seq>);
+      process-tokens(list-item-content, token-item-content);
+      list.items[i] := list-item-content;
+   end for;
+   add!(seq, list);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: type-union(<hyphenated-list-token>, <phrase-list-token>))
+=> ()
+   // <x-list-token> contains
+   //   <x-list-item-token> contains
+   //     <markup-seq> in item-label and <content-seq> in content
+   let token-items = token.token-content;
+   let list =
+         select (token.object-class)
+            <hyphenated-list-token> => make(<one-line-defn-list>);
+            <phrase-list-token> => make(<two-line-defn-list>);
+         end select;
+   list.items = make(<array>, dimensions: vector(2, token-items.size));
+   for (i from 0, token-item in token-items)
+      let list-item-label = make(<markup-seq>);
+      let list-item-content = make(<content-seq>);
+      process-tokens(list-item-label, token-item.item-label);
+      process-tokens(list-item-content, token-item.token-content);
+      list.items[0, i] := list-item-label;
+      list.items[1, i] := list-item-content;
+   end for;
+   add!(seq, list);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<topic-content-seq>, <content-seq>),
+    token :: <paragraph-token>)
+=> ()
+   let para = make(<paragraph>);
+   process-tokens(para.content, token.token-content);
+   add!(seq, para);
+end method;
+
+
+//
+// process-tokens for <code-block> and <pre>
+//
+
+define method process-tokens
+   (blk :: <pre>, seq :: <sequence>)
+=> ()
+   do(curry(process-tokens, blk), seq);
+end method;
+
+
+define method process-tokens
+   (blk :: <pre>, line-token :: <raw-line-token>)
+=> ()
+   when (line-token.token-index)
+      add!(blk.content, make(<ph-marker>, index: line-token.token-index));
+   end when;
+   add!(blk.content, concatenate(line-token.token-content, "\n"));
+end method;
+
+
+//
+// process-tokens for <markup-seq> and <title-seq>
+//
+
+define method process-tokens
+   (seq :: type-union(<markup-seq>, <title-seq>),
+    word :: <string>)
+=> ()
+   if (~seq.empty?) add!(seq, ' ') end;
+   add!(seq, word);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<markup-seq>, <title-seq>),
+    quote :: <quote-token>)
+=> ()
+   let elements = quote-elements(seq, quote, $default-quote-spec);
+   if (~instance?(elements, <sequence>))
+      elements := vector(elements);
+   end if;
+   if (~seq.empty?) add!(seq, ' ') end;
+   if (quote.prequoted-content) add!(seq, quote.prequoted-content) end;
+   seq := concatenate!(seq, elements);
+   if (quote.postquoted-content) add!(seq, quote.postquoted-content) end;
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<markup-seq>, <title-seq>),
+    image-ref :: <image-ref-token>)
+=> ()
+   let img = make(<inline-image>, image: image-ref.filename,
+                  alt-text: image-ref.caption | "");
+   add!(seq, img);
+end method;
+
+
+define method process-tokens
+   (seq :: type-union(<markup-seq>, <title-seq>),
+    block-tok :: <bracketed-render-block-token>)
+=> ()
+   let render-content =
+         make(if (block-tok.block-type = #"html") <html-content> else <dita-content> end,
+              content: block-tok.token-content);
+   add!(seq, render-content);
+end method;
+
+
+define method process-tokens
+   (seq :: <markup-seq>, ref :: <marker-ref-token>)
+=> ()
+   let marker = make(<marker-placeholder>, index: ref.token-index);
+   add!(seq, make(<xref>, target: marker));
+end method;
+
+
+define method process-tokens
+   (seq :: <markup-seq>, ref :: <synopsis-ref-token>)
+=> ()
+   let target = make(<target-placeholder>, link: ref.link);
+   add!(seq, make(<conref>, type: #"shortdesc", target: target));
+end method;
+
+
+/// Synopsis: Returns the intermediate elements that make up a quote.
+///
+/// Style changes affect the entire render. Link and monospace affect everything
+/// inside typographical quotes. The actual link tag is innermost so its text can
+/// be replaced easily by a topic title or an <api-name> or <parameter-name>
+/// object (perhaps surrounded by an <xref>).
+///
+/// To support that, from innermost to outermost, the quoted text is wrapped in:
+/// link-placeholder, term, code, typographical quotes, bib, b, i, u, term formatting, em
+///
+define method quote-elements
+   (quote-owner :: type-union(<title-seq>, <markup-seq>),
+    quote :: <quote-token>, default-specs :: <table>)
+=> (outer-quote-elem :: <interm-element>)
+   let specs = check-quote-specifiers(quote, default-specs,
+         for-title: instance?(quote-owner, <title-seq>));
+   let interior =
+         if (member?(#"sic", specs))
+            concatenate(quote.open-quote, quote.quoted-content, quote.close-quote)
+         else
+            quote.quoted-content
+         end if;
+   let (link-target, link-text) =
+         if (instance?(specs.last, <string>))
+            values(make(<target-placeholder>, link: specs.last),
+                   interior)
+         else
+            values(make(<target-placeholder>, link: interior),
+                   make(<conref>, style: #"title", target: interior))
+         end if;
+   let first-term = #t;
+
+   for (spec in choose(rcurry(member?, specs),
+         #[ #"qv", #"toc", #"term", #"code", #"q", #"qq", #"bib", #"b", #"i", #"u", #"term", #"em" ]))
+      let new-interior = 
+            select (spec)
+               #"qv", #"toc" =>
+                  let link = make( if (spec = #"toc") <toc-xref> else <xref> end );
+                  link.text := link-text;
+                  link.target := link-target;
+                  link;
+               #"term" =>
+                  let term = make( if (first-term) <term> else <term-style> end );
+                  term.text := interior;
+                  first-term := #f;
+                  term;
+               #"code" =>
+                  let phrase = make(<code-phrase>);
+                  phrase.text := interior;
+                  phrase;
+               #"q" =>
+                  if (~instance?(interior, <sequence>))
+                     interior := vector(interior);
+                  end if;
+                  // left and right single curly quotes
+                  let left-quote = vector(make(<entity>, code: #x2018));
+                  let right-quote = vector(make(<entity>, code: #x2019));
+                  concatenate-as(<markup-seq>, left-quote, interior, right-quote);
+               #"qq" =>
+                  if (~instance?(interior, <sequence>))
+                     interior := vector(interior);
+                  end if;
+                  // left and right double curly quotes
+                  let left-quote = vector(make(<entity>, code: #x201C));
+                  let right-quote = vector(make(<entity>, code: #x201D));
+                  concatenate-as(<markup-seq>, left-quote, interior, right-quote);
+               #"bib" =>
+                  let cite = make(<cite>);
+                  cite.text := interior;
+                  cite;
+               #"b" =>
+                  let bold = make(<bold>);
+                  bold.text := interior;
+                  bold;
+               #"i" =>
+                  let ital = make(<italic>);
+                  ital.text := interior;
+                  ital;
+               #"u" =>
+                  let ul = make(<underline>);
+                  ul.text := interior;
+                  ul;
+               #"em" =>
+                  let em = make(<emphasis>);
+                  em.text := interior;
+                  em;
+            end select;
+      interior := new-interior;
+   end for;
+   interior
+end method;

Modified: trunk/sandbox/dydoc/markup-translator/module.dylan
==============================================================================
--- trunk/sandbox/dydoc/markup-translator/module.dylan	(original)
+++ trunk/sandbox/dydoc/markup-translator/module.dylan	Fri May  9 04:06:20 2008
@@ -4,7 +4,8 @@
 
 define module markup-translator
    use common;
-   use markup-parser, rename: { content => token-content };
+   use markup-parser,
+      rename: { content => token-content, index => token-index };
    use internal-rep;
    use ordered-tree;
    use configs;

Added: trunk/sandbox/dydoc/markup-translator/topic-processing.dylan
==============================================================================
--- (empty file)
+++ trunk/sandbox/dydoc/markup-translator/topic-processing.dylan	Fri May  9 04:06:20 2008
@@ -0,0 +1,174 @@
+module: markup-translator
+
+/// Synopsis: An umbrella type.
+define constant <topic-token> =
+      type-union(<topic-directive-token>, <titled-topic-token>);
+      
+/// [ditto <topic-token>]
+define constant <section-token> =
+      type-union(<paragraph-directive-token>, <indented-directive-token>);
+
+
+/// Synopsis: Returns <topic>s from a markup block.
+define method process-markup
+   (tokens :: <sequence>, context-topic :: false-or(<topic>))
+=> (result :: <sequence>)
+   let (topics, bare-content) = partition(non-section-topic?, tokens);
+
+   when (~bare-content.empty?)
+      // Put bare content into context topic.
+      when (~context-topic)
+         error(make(<simple-warning>, format-string:
+               "Please provide a topic; no implicit topic found for this location."))
+      end when;
+      process-tokens(context-topic, as(<sequence>, bare-content));
+   end when;
+
+   concatenate(if (context-topic) vector(context-topic) else #() end,
+               map(make-topic-from-token, topics));
+   
+   // TODO: Resolve markers and footnotes.
+end method;
+
+
+/// Synopsis: Generate a topic from a topic token.
+define generic make-topic-from-token (token :: <topic-token>)
+=> (topic :: <topic>);
+
+
+define method make-topic-from-token (token :: <topic-directive-token>)
+=> (topic :: <api-doc>)
+   // token.topic-title is a simple string, but topic.title is a <title-seq>.
+   // topic.id is specified in automatic topic created by scanning an API.
+   let topic = make(<api-doc>, topic-type: token.topic-type);
+   add!(topic.title, token.topic-title);
+   check-topic-title(topic.title);
+   check-topic-id(topic.id);
+
+   process-tokens(topic, token.token-content);
+   topic
+end method;
+
+
+define method make-topic-from-token (token :: <titled-topic-token>)
+=> (topic :: <con-topic>)
+   // TODO: Topic fixed-parent needs to be computed. Where? Add level style to <topic>?
+   let topic = make(<con-topic>, id: token.topic-nickname);
+   process-tokens(topic.title, token.topic-title);
+   check-topic-title(topic.title);
+   check-topic-id(topic.id);
+
+   process-tokens(topic, token.token-content);
+   topic
+end method;
+
+
+/// Generic Function: process-tokens
+///
+/// Synopsis: Add a token into an intermediate object, merging if necessary.
+///
+/// 'Owner' could be the object itself or the value of some slot of the object. We
+/// don't call this method on the content slot of a topic, because 'tokens' may
+/// include things that affect the topic itself, and the topic isn't reachable
+/// from its content slot.
+///
+/// Arguments:
+///   owner - An intermediate object or content sequence.
+///   tokens - The token or tokens to process and add to 'owner'.
+///
+define generic process-tokens
+   (owner :: type-union(<interm-element>, <content-seq>, <markup-seq>,
+                        <title-seq>, <topic-content-seq>),
+    tokens :: type-union(<token>, <sequence>))
+=> ();
+
+
+//
+// process-tokens for <topic>s
+//
+
+define method process-tokens
+   (topic :: <topic>, section-token :: <section-token>)
+=> ()
+   check-allowed-sections(section-token, topic);
+   select (section-token.directive-type)
+      #"synopsis" =>
+         check-no-shortdesc(topic);
+         topic.shortdesc := make(<paragraph>);
+         process-tokens(topic.shortdesc, section-token.token-content);
+      #"keywords", #"conditions", #"arguments", #"values" =>
+         // TODO: Ensure user hasn't specified multiple of these, like we do
+         // for #"synopsis". Should generalize check-no-shortdesc.
+         let (setter, section-id, section-title) =
+               select (section-token.directive-type)
+                  #"keywords" =>
+                     values(keywords-section-setter, ":Keywords", "Make Keywords");
+                  #"conditions" =>
+                     values(conds-section-setter, ":Conditions", "Conditions");
+                  #"arguments" =>
+                     values(args-section-setter, ":Arguments", "Arguments");
+                  #"values" =>
+                     values(vals-section-setter, ":Values", "Values");
+               end select;
+         let section = make(<section>, id: section-id);
+         process-tokens(section.title, section-title);
+         process-tokens(section.content, section-token.token-content);
+         setter(section, topic);
+      #"note", #"warning" =>
+         let note-class = select (section-token.directive-type)
+                             #"note" => <note>;
+                             #"warning" => <warning-note>;
+                          end select;
+         let note = make(note-class);
+         process-tokens(note.content, section-token.token-content);
+         add!(topic.content, note);
+   end select;
+end method;
+
+
+define method process-tokens
+   (topic :: <topic>, section-token :: <link-directive-token>)
+=> ()
+   let target = make(<target-placeholder>, link: section-token.link);
+   select (section-token.directive-type)
+      #"section" => topic.parent := target;
+   end select;
+end method;
+
+
+/// Fallback method puts tokens in 'topic.content'.
+define method process-tokens
+   (topic :: <topic>, token :: <token>)
+=> ()
+   process-tokens(topic.content, token)
+end method;
+
+
+//
+// process-tokens for <topic-content-seq>
+//
+
+/// Will only be called for <titled-topic-token>s that are sections; topics
+/// will have been separated by 'process-markup' already.
+define method process-tokens
+   (topic-seq :: <topic-content-seq>, section-token :: <titled-topic-token>)
+=> ()
+   debug-assert(~non-section-topic?, "Non-section being added to topic");
+
+   let section = make(<section>, id: section-token.topic-nickname);
+   process-tokens(section.title, section-token.topic-title);
+   check-topic-title(section.title);
+   check-topic-id(section.id);
+
+   process-tokens(section.content, section-token.token-content);
+   add!(topic-seq, section);
+end method;
+
+
+define method process-tokens
+   (topic-seq :: <topic-content-seq>, token :: <footnote-token>)
+=> ()
+   let footnote = make(<footnote>, index: token.token-index);
+   process-tokens(footnote.content, token.token-content);
+   add!(topic-seq, footnote);
+end method;

Modified: trunk/sandbox/dydoc/support/common.dylan
==============================================================================
--- trunk/sandbox/dydoc/support/common.dylan	(original)
+++ trunk/sandbox/dydoc/support/common.dylan	Fri May  9 04:06:20 2008
@@ -15,14 +15,42 @@
 end function;
 
 
+/// Synopsis: Define methods to visit objects and their slots.
+///
+/// Use as follows, where braces indicate optional items:
+/// : define {collection-recursive} slot-visitor NAME
+/// :   CLASS {, SLOT}... ;
+/// :   {CLASS {, SLOT}... ;}...
+/// : end {slot-visitor {NAME}}
+///
+/// This defines a set of visitor methods called NAME. The methods have this
+/// signature:
+/// : NAME (object :: CLASS, action :: <function>, #key KEY, ...) => ()
+/// 
+/// The method visits all SLOTS then the object itself, performing the action.
+/// The action should have this signature:
+/// : (object {:: TYPE}, #key setter, KEY, ...) => ()
+///
+/// The action is called on the object or slot value. If the TYPE doesn't match,
+/// the action is not performed. The setter key is a function by which the action
+/// can replace replace the object or slot value. ALL-KEYS passed to each NAME
+/// function is also passed to the ACTION.
+///
 define macro slot-visitor-definer
    { define collection-recursive slot-visitor ?:name ?classes:* end }
    => {
-         define method ?name (collection :: <collection>, operation :: <function>)
-            do(rcurry(?name, operation), collection);
+         define method ?name
+            (col :: <collection>, f :: <function>, #rest keys, #key, #all-keys)
+         => ()
+            for (o keyed-by i in col)
+               apply(?name, o, f, #"setter", rcurry(element-setter, col, i),
+                     keys);
+            end for;
          end method;
 
-         define method ?name (collection :: <object>, operation :: <function>)
+         define method ?name
+            (o :: <object>, f :: <function>, #key, #all-keys)
+         => ()
          end method;
 
          define slot-visitor ?name ?classes end;
@@ -39,11 +67,18 @@
    
    { class-visitors(?:name; ?class-name:name, ?slots; ?more:*) }
    => {
-         define method ?name (object :: ?class-name, operation :: <function>)
-            for (slot in vector(?slots))
-               ?name(object.slot, operation)
+         define method ?name
+            (object :: ?class-name, action :: <function>, #rest keys, #key, #all-keys)
+         => ()
+            for (slot in vector(?slots),
+                 setter in setters-vector(?slots))
+               apply(?name, object.slot, action,
+                     #"setter", rcurry(setter, object), keys)
             end for;
-            operation(object);
+
+            when (instance?(object, action.function-specializers.first))
+               apply(action, object, keys);
+            end when;
          end method;
          
          class-visitors(?name; ?more)
@@ -53,3 +88,13 @@
    { ?:name, ... } => { ?name, ... }
    { } => { }
 end macro;
+
+
+define macro setters-vector
+   { setters-vector(?getters) } => { vector(?getters) }
+   { setters-vector() } => { }
+
+getters:
+   { ?:name, ... } => { ?name ## "-setter", ... }
+   { } => { }
+end macro;

Modified: trunk/sandbox/dydoc/topic-resolver/resolving.dylan
==============================================================================
--- trunk/sandbox/dydoc/topic-resolver/resolving.dylan	(original)
+++ trunk/sandbox/dydoc/topic-resolver/resolving.dylan	Fri May  9 04:06:20 2008
@@ -26,24 +26,22 @@
 => (resolved-topics :: <sequence>)
    let defined-ids = topics-by-id(topics);
    let (defined-titles, dup-titles) = topics-by-title(topics);
-   let unknown-links = #();
-   visit-placeholders(topics,
-         method (placeholder)
-            when (instance?(placeholder, <target-placeholder>))
-               unknown-links := add!(unknown-links, placeholder)
-            end when
-         end method);
-   
-   for (link in unknown-links)
-      let topic = resolve-link(link, defined-titles, defined-ids);
-      if (topic)
-         fix-link(link, topic)
-      elseif (~member?(link.target, dup-titles, test: case-insensitive-equal))
-         error("Topic or tag \"%s\" not found in link at %s",
-               link.target, link.element-source);
-      end if;
-   end for;
-   topics
+   // resolve-placeholders(topics, setter: #f,
+   //                      id-topics: defined-ids,
+   //                      title-topics: defined-titles,
+   //                      dup-titles: dupe-titles);
+   visit-placeholders(
+         topics,
+         method (link :: <target-placeholder>, #key setter) => ()
+            let topic = resolve-link(link, defined-titles, defined-ids);
+            if (topic)
+               setter(topic)
+            elseif (~member?(link.target, dup-titles, test: case-insensitive-equal))
+               error("Topic or tag \"%s\" not found in link at %s",
+                     link.target, link.element-source);
+            end if;
+         end);
+   topics;
 end method;
 
 
@@ -91,32 +89,158 @@
 end method;
 
 
-/// General function: fix-link
-/// Synopsis: Replaces a <target-placeholder> with a real target.
-define generic fix-link (object :: <interm-element>, topic :: <topic>, #key) => ();
-
-/// This method is the basic callee.
-define method fix-link (link :: <target-placeholder>, topic :: <topic>, #key) => ()
-   fix-link(link.element-owner, topic, link: link)
-end method;
-
-/// This method is for all intermediate elements that have a 'target' slot
-/// containing the link.
-define method fix-link (owner :: <interm-element>, topic :: <topic>, #key link) => ()
-   owner.target := topic
-end method;
-
-/// <topic> doesn't have a 'target' slot, but has 'relevant-to', 'see-also',
-/// and 'parent'. See which of them has the placeholder.
-define method fix-link (owner :: <topic>, topic :: <topic>, #key link) => ()
-   let parent? = (owner.parent = link);
-   let see-also-key = find-key(owner.see-also, curry(\=, link));
-   let relevant-to-key = find-key(owner.relevant-to, curry(\=, link));
-   if (parent?) owner.parent := topic end if;
-   if (see-also-key) owner.see-also[see-also-key] := topic end if;
-   if (relevant-to-key) owner.relevant-to[relevant-to-key] := topic end if;
+/*
+/// Generic Function: resolve-placeholders
+/// Synopsis: Replaces <target-placeholder>s in objects with a real topic.
+/// Arguments:
+///   object        - A object in which to resolve <target-placeholder>s.
+///   setter:       - A function taking one argument that can replace the
+///                   <target-placeholder> with another object.
+///   id-topics:    - A table of <topic> keyed by id string.   
+///   title-topics: - A table of <topic> keyed by title string.
+///   dup-titles:   - A sequence of title strings used in more that one place.
+///
+define generic resolve-placeholders
+   (object, #key setter, id-topics, title-topics, dup-titles)
+=> ();
+
+/// Actually do the resolution.
+define method resolve-placeholders
+   (link :: <target-placeholder>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   let topic = resolve-link(link, title-topics, id-topics);
+   if (topic)
+      setter(topic)
+   elseif (~member?(link.target, dup-titles, test: case-insensitive-equal))
+      error("Topic or tag \"%s\" not found in link at %s",
+            link.target, link.element-source);
+   end if;
+end method;
+
+/// Recurses into sequences, markup sequences, and arrays. <title-markup> won't
+/// have any <target-placeholder>s.
+define method resolve-placeholders
+   (seq :: <collection>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   for (o keyed-by i in seq)
+      resolve-placeholders(o, setter: rcurry(element-setter, seq, i),
+                           id-topics, title-topics, dup-titles);
+   end for;
+end method;
+
+/// Nothing to do for most objects.
+define method resolve-placeholders
+   (obj :: <object>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+end method;
+
+define method resolve-placeholders
+   (topic :: <topic>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(topic.content, setter: rcurry(content-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.shortdesc, setter: rcurry(shortdesc-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.parent, setter: rcurry(parent-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.see-also, setter: rcurry(see-also-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.relevant-to, setter: rcurry(relevant-to-setter, topic),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+define method resolve-placeholders
+   (topic :: <class-doc>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   next-method();
+   resolve-placeholders(topic.keywords-section,
+                        setter: rcurry(keywords-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+define method resolve-placeholders
+   (topic :: <function-doc>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   next-method();
+   resolve-placeholders(topic.args-section,
+                        setter: rcurry(args-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.vals-section,
+                        setter: rcurry(vals-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.conds-section,
+                        setter: rcurry(conds-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
 end method;
 
+define method resolve-placeholders
+   (topic :: <function-doc>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   next-method();
+   resolve-placeholders(topic.args-section,
+                        setter: rcurry(args-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(topic.vals-section,
+                        setter: rcurry(vals-section-setter, topic),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+/// Recurses into quote elements.
+define method resolve-placeholders
+   (obj :: type-union(<bold>, <cite>, <code-phrase>, <emphasis>, <italic>,
+                      <term-style>, <term>, <underline>),
+    #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.text, setter: rcurry(text-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+/// Recurses into list elements.
+define method resolve-placeholders
+   (obj :: type-union(<defn-list>, <ordered-list>, <unordered-list>),
+    #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.items, setter: rcurry(items-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+define method resolve-placeholders
+   (obj :: <simple-table>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.headings, setter: rcurry(headings-setter, obj),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(obj.items, setter: rcurry(items-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+/// Recurses into elements with targets (except for <target-placeholder>).
+define method resolve-placeholders
+   (obj :: type-union(<conref>, <ditto-placeholder>, <toc-xref>),
+    #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.target, setter: rcurry(target-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+/// Recurses into elements with content.
+define method resolve-placeholders
+   (obj :: type-union(<paragraph>, <footnote>),
+    #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.content, setter: rcurry(content-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+
+define method resolve-placeholders
+   (obj :: <section>, #key setter, id-topics, title-topics, dup-titles)
+=> ()
+   resolve-placeholders(obj.title, setter: rcurry(title-setter, obj),
+                        id-topics, title-topics, dup-titles);
+   resolve-placeholders(obj.content, setter: rcurry(content-setter, obj),
+                        id-topics, title-topics, dup-titles);
+end method;
+*/
+
 
 /// Synopsis: Determines what topic a link refers to.
 ///
@@ -147,3 +271,42 @@
    end if;
    topic
 end method;
+
+
+/// Generic Function: visit-placeholders
+/// Synopsis: Visits a <topic> and its nested elements that can contain
+/// <target-placeholder> objects.
+///
+/// Arguments:
+///   element     - The <interm-element> to visit.
+///   operation   - A <function> on 'element'. The function is passed a
+///                 setter: argument.
+
+define collection-recursive slot-visitor visit-placeholders
+   <bold>,                 text;
+   <cite>,                 text;
+   <class-doc>,            content, shortdesc, parent, see-also, relevant-to,
+                           keywords-section;
+   <code-phrase>,          text;
+   <conref>,               target;
+   <defn-list>,            items;
+   <ditto-placeholder>,    target;
+   <emphasis>,             text;
+   <footnote>,             content;
+   <function-doc>,         content, shortdesc, parent, see-also, relevant-to,
+                           args-section, vals-section, conds-section;
+   <italic>,               text;
+   <macro-doc>,            content, shortdesc, parent, see-also, relevant-to,
+                           args-section, vals-section;
+   <ordered-list>,         items;
+   <paragraph>,            content;
+   <section>,              title, content;
+   <simple-table>,         headings, items;
+   <target-placeholder>,   ;
+   <term-style>,           text;
+   <term>,                 text;
+   <toc-xref>,             target;
+   <topic>,                content, shortdesc, parent, see-also, relevant-to;
+   <underline>,            text;
+   <unordered-list>,       items;
+end slot-visitor;

Modified: trunk/sandbox/dydoc/topic-resolver/visitors.dylan
==============================================================================
--- trunk/sandbox/dydoc/topic-resolver/visitors.dylan	(original)
+++ trunk/sandbox/dydoc/topic-resolver/visitors.dylan	Fri May  9 04:06:20 2008
@@ -1,45 +1,5 @@
 module: topic-resolver
 
-/// Generic Function: visit-placeholders
-/// Synopsis: Visits a <topic> and its nested elements that can contain
-/// <target-placeholder> objects.
-///
-/// Arguments:
-///   element     - The <interm-element> to visit.
-///   operation   - A <function> on 'element'.
-/// Values:
-///   result      - The result of 'operation'.
-
-define collection-recursive slot-visitor visit-placeholders
-   <bold>,	               text;
-   <cite>,	               text;
-   <class-doc>,	         content, shortdesc, parent, see-also, relevant-to,
-                           keywords-section;
-   <code-phrase>,	         text;
-   <conref>,	            target;
-   <defn-list>,	         items;
-   <ditto-placeholder>,	   target;
-   <emphasis>,	            text;
-   <footnote>,	            content;
-   <function-doc>,	      content, shortdesc, parent, see-also, relevant-to,
-                           args-section, vals-section, conds-section;
-   <italic>,	            text;
-   <macro-doc>,	         content, shortdesc, parent, see-also, relevant-to,
-                           args-section, vals-section;
-   <ordered-list>,	      items;
-   <paragraph>,	         content;
-   <section>,	            title, content;
-   <simple-table>,	      headings, items;
-   <target-placeholder>,   ;
-   <term-style>,	         text;
-   <term>,	               text;
-   <toc-xref>,	            target;
-   <topic>,	               content, shortdesc, parent, see-also, relevant-to;
-   <underline>,	         text;
-   <unordered-list>,	      items;
-end slot-visitor;
-
-
 /// Generic Function: visit-toc-xrefs
 /// Synopsis: Visits a <topic> and its nested elements that can contain <toc-xref>
 /// objects.
@@ -47,8 +7,7 @@
 /// Arguments:
 ///   element     - The <interm-element> to visit.
 ///   operation   - A <function> on 'element'.
-/// Values:
-///   result      - The result of 'operation'.
+///   #rest keys  - A set of keys passed to 'operation'.
 
 define collection-recursive slot-visitor visit-toc-xrefs
    <bold>,	          text;


More information about the chatter mailing list