Skip to content

Commit c49e89c

Browse files
authored
Merge pull request #2198 from rust-lang/TC/support-grammar-rules-in-link-definitions
Resolve grammar rules in link reference definitions
2 parents caa4205 + f7e2b38 commit c49e89c

4 files changed

Lines changed: 60 additions & 0 deletions

File tree

dev-guide/src/grammar.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,19 @@ The [`mdbook-spec`] plugin automatically adds Markdown link definitions for all
154154

155155
In some cases, there might be name collisions with the automatic linking of rule names. In that case, disambiguate with the `grammar-` prefix, such as `[Type][grammar-Type]`. The prefix can also be used when explicitness would aid clarity.
156156

157+
Production names can also be used in link reference definitions to provide custom link text, both with and without the `grammar-` prefix.
158+
159+
```markdown
160+
We accept any [type].
161+
162+
[type]: grammar-Type
163+
```
164+
165+
```markdown
166+
We accept any [type].
167+
168+
[type]: Type
169+
```
170+
157171
[`mdbook-spec`]: tooling/mdbook-spec.md
158172
[Notation]: https://doc.rust-lang.org/nightly/reference/notation.html

dev-guide/src/links.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ Link definitions are automatically generated for all grammar production names. S
7474
This attribute uses the [MetaWord] syntax.
7575

7676
Explicit grammar links can have the `grammar-` prefix like [Type][grammar-Type].
77+
78+
Grammar links can also appear in link reference definitions, e.g. [type].
79+
80+
[type]: grammar-Type
7781
```
7882

7983
## Outside book links

tools/mdbook-spec/src/grammar.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,47 @@ pub fn insert_grammar(grammar: &Grammar, chapter: &Chapter, diag: &mut Diagnosti
7575
content
7676
}
7777

78+
/// Converts link reference definitions that point to a grammar rule
79+
/// to the correct link.
80+
///
81+
/// For example:
82+
///
83+
/// ```markdown
84+
/// We accept any [token].
85+
///
86+
/// [token]: grammar-Token
87+
/// ```
88+
///
89+
/// This will convert the `[token]` definition to point
90+
/// to the actual link.
91+
///
92+
/// This supports both a `grammar-` prefixed form (e.g.
93+
/// `grammar-Token`) and a bare rule name (e.g. `Token`).
94+
pub fn grammar_link_references(chapter: &Chapter, grammar: &Grammar) -> String {
95+
let current_path = chapter.path.as_ref().unwrap().parent().unwrap();
96+
let for_summary = is_summary(chapter);
97+
crate::MD_LINK_REFERENCE_DEFINITION
98+
.replace_all(&chapter.content, |caps: &Captures<'_>| {
99+
let dest = &caps["dest"];
100+
let name = dest.strip_prefix("grammar-").unwrap_or(dest);
101+
if let Some(production) = grammar.productions.get(name) {
102+
let label = &caps["label"];
103+
let relative = pathdiff::diff_paths(&production.path, current_path).unwrap();
104+
// Adjust paths for Windows.
105+
let relative = relative.display().to_string().replace('\\', "/");
106+
let id = render_markdown::markdown_id(name, for_summary);
107+
if for_summary {
108+
format!("[{label}]: #{id}")
109+
} else {
110+
format!("[{label}]: {relative}#{id}")
111+
}
112+
} else {
113+
caps.get(0).unwrap().as_str().to_string()
114+
}
115+
})
116+
.to_string()
117+
}
118+
78119
/// Creates a map of production name -> relative link path.
79120
fn make_relative_link_map(grammar: &Grammar, chapter: &Chapter) -> HashMap<String, String> {
80121
let current_path = chapter.path.as_ref().unwrap().parent().unwrap();

tools/mdbook-spec/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ impl Preprocessor for Spec {
168168
}
169169
ch.content = admonitions::admonitions(&ch, &mut diag);
170170
ch.content = self.rule_link_references(&ch, &rules);
171+
ch.content = grammar::grammar_link_references(&ch, &grammar);
171172
ch.content = self.auto_link_references(&ch, &rules);
172173
ch.content = self.render_rule_definitions(&ch.content, &tests, &git_ref);
173174
if ch.name == "Test summary" {

0 commit comments

Comments
 (0)