From 18d35b8c781cba5a5c6976da793724cb5efbe9c5 Mon Sep 17 00:00:00 2001 From: lukaslueg Date: Sat, 10 Oct 2026 15:17:19 +0200 Subject: [PATCH] Bump railroad-dependency --- Cargo.lock | 4 +- theme/reference.css | 5 - tools/mdbook-spec/Cargo.toml | 2 +- .../src/grammar/render_railroad.rs | 98 +++++++------------ 4 files changed, 39 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47e2054d73..774f490f71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,9 +563,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "railroad" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7286d8b4d9fc00078819e06ff24cefa276f39461ff53b74d63d24736be27192f" +checksum = "ab680249ce22bf009ea6e6e1340c7a9e7af01dbec3a4751b7956b0c265b590c1" dependencies = [ "unicode-width", ] diff --git a/theme/reference.css b/theme/reference.css index fa48768881..ffe86571ed 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -686,8 +686,3 @@ html.navy svg.railroad, html.ayu svg.railroad { background-color: hsl(from var(--bg) h s calc(l + 5)); } - -/* Styling specific to the Reference's negative-lookahead railroad node. */ -svg.railroad g.exceptbox > rect { - fill:rgba(245, 160, 125, .1); -} diff --git a/tools/mdbook-spec/Cargo.toml b/tools/mdbook-spec/Cargo.toml index 68b9aefabe..b90022f133 100644 --- a/tools/mdbook-spec/Cargo.toml +++ b/tools/mdbook-spec/Cargo.toml @@ -16,7 +16,7 @@ mdbook-markdown = "0.5.1" mdbook-preprocessor = "0.5.1" once_cell = "1.19.0" pathdiff = "0.2.1" -railroad = { version = "0.3.9", default-features = false } +railroad = { version = "0.3.10", default-features = false } regex = "1.12.2" semver = "1.0.21" serde_json = "1.0.113" diff --git a/tools/mdbook-spec/src/grammar/render_railroad.rs b/tools/mdbook-spec/src/grammar/render_railroad.rs index 405e7e2910..75d89d3100 100644 --- a/tools/mdbook-spec/src/grammar/render_railroad.rs +++ b/tools/mdbook-spec/src/grammar/render_railroad.rs @@ -175,10 +175,17 @@ fn render_expression(expr: &Expression, cx: &RenderCtx, stack: bool) -> Option { - let forward = render_expression(e, cx, stack)?; - let lbox = - LabeledBox::new(forward, Comment::new("not followed by".to_string())); - Box::new(lbox) + let forward = Sequence::new(vec![ + render_expression(e, cx, stack)?, + Box::new(Continuation), + ]); + Box::new(Annotation::new_ahead(Scale::new( + LabeledBox::new( + forward, + Comment::new("⚠️ Ahead must not match".to_owned()), + ), + 0.85, + ))) } // Treat `e?` and `e{..=1}` / `e{0..=1}` equally. ExpressionKind::Optional(e) @@ -313,9 +320,8 @@ fn render_expression(expr: &Expression, cx: &RenderCtx, stack: bool) -> Option unreachable!("closed range must have upper bound"), ExpressionKind::RepeatRangeNamed(e, name) => { let n = render_expression(e, cx, stack)?; - let cmt = format!("repeat exactly {name} times"); - let lbox = LabeledBox::new(n, Comment::new(cmt)); - Box::new(lbox) + let cmt = format!("repeat exactly `{name} - 1` times"); + Box::new(Repeat::new(n, Comment::new(cmt))) } ExpressionKind::Nt(nt) => node_for_nt(cx, nt), ExpressionKind::Terminal(t) => Box::new(Terminal::new(t.clone())), @@ -342,9 +348,16 @@ fn render_expression(expr: &Expression, cx: &RenderCtx, stack: bool) -> Option { - let n = render_expression(e, cx, stack)?; + let n = Sequence::new(vec![ + Box::new(Continuation) as Box, + render_expression(e, cx, stack)?, + ]); let ch = node_for_nt(cx, "CHAR"); - Box::new(Except::new(Box::new(ch), n)) + let assertion = Box::new(Annotation::new_behind(Scale::new( + LabeledBox::new(n, Comment::new("⚠️ Prior must not match".to_owned())), + 0.85, + ))); + Box::new(Sequence::new(vec![ch, assertion])) } ExpressionKind::Cut(e) => { let rhs = render_expression(e, cx, stack)?; @@ -361,7 +374,7 @@ fn render_expression(expr: &Expression, cx: &RenderCtx, stack: bool) -> Option } else { @@ -410,45 +423,6 @@ fn strip_markdown(s: &str) -> String { LINK_RE.replace_all(s, "$1").to_string() } -struct Except { - inner: LabeledBox, Box>, -} - -impl Except { - fn new(inner: Box, label: Box) -> Self { - let grid = Box::new(VerticalGrid::new(vec![ - Box::new(Comment::new("⚠️ with the exception of".to_owned())) as Box, - label, - ])) as Box; - let mut this = Self { - inner: LabeledBox::new(inner, grid), - }; - this.inner - .attr("class".to_owned()) - .or_default() - .push_str(" exceptbox"); - this - } -} - -impl Node for Except { - fn entry_height(&self) -> i64 { - self.inner.entry_height() - } - - fn height(&self) -> i64 { - self.inner.height() - } - - fn width(&self) -> i64 { - self.inner.width() - } - - fn draw(&self, x: i64, y: i64, h_dir: svg::HDir) -> svg::Element { - self.inner.draw(x, y, h_dir) - } -} - #[cfg(test)] mod tests { use super::*; @@ -574,7 +548,7 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("not followed by"), + svg.contains("Ahead must not match"), "should contain the 'not followed by' label" ); assert!(svg.contains("CHAR"), "should contain the nonterminal name"); @@ -590,7 +564,7 @@ mod tests { 0, ); let svg = render_to_svg(&expr).unwrap(); - assert!(svg.contains("not followed by")); + assert!(svg.contains("Ahead must not match")); assert!(svg.contains("CR")); } @@ -607,7 +581,7 @@ mod tests { 0, ); let svg = render_to_svg(&expr).unwrap(); - assert!(svg.contains("not followed by")); + assert!(svg.contains("Ahead must not match")); assert!(svg.contains("e")); assert!(svg.contains("E")); } @@ -699,7 +673,7 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("with the exception of"), + svg.contains("Prior must not match"), "neg expression should have exception label" ); } @@ -708,7 +682,7 @@ mod tests { #[test] fn repeat_range_named_reference() { - // RepeatRangeNamed renders with a "repeat exactly n times" + // RepeatRangeNamed renders with a "repeat exactly `n` times" // label. let expr = Expression::new_kind( ExpressionKind::RepeatRangeNamed( @@ -719,8 +693,8 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("repeat exactly n times"), - "expected 'repeat exactly n times' label, got: {svg}" + svg.contains("repeat exactly `n - 1` times"), + "expected 'repeat exactly `n - 1` times' label, got: {svg}" ); } @@ -739,8 +713,8 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("repeat count n"), - "expected 'repeat count n' label, got: {svg}" + svg.contains("repeat count `n`"), + "expected 'repeat count `n`' label, got: {svg}" ); } @@ -760,8 +734,8 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("repeat count k"), - "expected 'repeat count k' label, got: {svg}" + svg.contains("repeat count `k`"), + "expected 'repeat count `k`' label, got: {svg}" ); } @@ -802,8 +776,8 @@ mod tests { ); let svg = render_to_svg(&expr).unwrap(); assert!( - svg.contains("repeat count n"), - "expected 'repeat count n' label on identity range" + svg.contains("repeat count `n`"), + "expected 'repeat count `n`' label on identity range" ); } }