use std::fs; use std::io::Write; fn main() { use railroad::*; let mut f = fs::File::create("examples/visuals.html").unwrap(); macro_rules! hr { () => { f.write_all(b"
").unwrap(); }; } macro_rules! raw_dia { ($r:expr) => { let dia = Diagram::with_default_css($r); writeln!(f, "
{}
", dia.width(), dia).unwrap(); }; } macro_rules! dia { ($r:expr) => { raw_dia!(seq!(SimpleStart, $r, SimpleEnd)); }; } macro_rules! nonterm { ($r:expr) => { NonTerminal::new($r.to_owned()) }; } macro_rules! term { ($r:expr) => { Terminal::new($r.to_owned()) }; } macro_rules! seq { ($($r: expr),*) => { Sequence::>::new(vec![ $( Box::new($r), )+ ]) } } macro_rules! choice { ($($r: expr),*) => { Choice::>::new(vec![ $( Box::new($r), )* ]) } } macro_rules! stck { ($($r: expr),*) => { Stack::>::new(vec![ $( Box::new($r), )* ]) } } macro_rules! cmt { ($r:expr) => { Comment::new($r.to_owned()) }; } macro_rules! vert { ($($r: expr),*) => { VerticalGrid::new(vec![ $( Box::new($r) as Box, )+ ]) } } macro_rules! horiz { ($($r: expr),*) => { HorizontalGrid::new(vec![ $( Box::new($r) as Box, )+ ]) } } macro_rules! lnk { ($r:expr) => { Link::new($r, "https://www.rust-lang.org".to_owned()) }; } macro_rules! rpt { ($r:expr, $s:expr) => { Repeat::new($r, $s) }; ($r:expr) => { rpt!($r, Empty) }; } macro_rules! dbg { ($eh:expr, $h:expr, $w:expr) => { Debug::new($eh, $h, $w) }; () => { dbg!(20, 30, 50) }; } macro_rules! opt { ($r:expr) => { Optional::new($r) }; } macro_rules! lbox { ($r:expr, $u:expr) => { LabeledBox::new($r, $u) }; ($r:expr) => { LabeledBox::new($r, Empty) }; } f.write_all(b"").unwrap(); f.write_all( br#" Railroad diagram examples "#, ) .unwrap(); // Very simple dia!(nonterm!("Foo")); dia!(lbox!(nonterm!("Foo"))); dia!(lbox!(nonterm!("Foo"), cmt!("Read the docs regarding foo!"))); hr!(); // Very simple, varying size dia!(dbg!()); dia!(dbg!(20, 50, 50)); hr!(); // Long text, difficult width dia!(nonterm!( "This is a very long text that should not escape it's bounding box, like ever..." )); dia!(term!( "This is a very long text that should not escape it's bounding box, like ever..." )); dia!(cmt!( "This is a very long text that should not escape it's bounding box, like ever..." )); dia!(term!("大家好")); dia!(cmt!("foobar")); dia!(lbox!( nonterm!("大家好 🤸"), cmt!("foobarfoobarfoobar") )); hr!(); // Optional dia!(opt!(dbg!(0, 20, 10))); dia!(opt!(dbg!(25, 45, 20))); dia!(opt!(dbg!(30, 50, 50))); hr!(); // Sequences of varying size dia!(seq!(dbg!(20, 30, 10), dbg!(30, 50, 70))); dia!(seq!(dbg!(20, 30, 10), dbg!(20, 50, 50), dbg!(30, 50, 70))); hr!(); // Choices dia!(choice!()); dia!(choice!(Empty)); dia!(choice!(Empty, Empty)); dia!(choice!(Empty, dbg!(5, 25, 10))); dia!(choice!(dbg!(15, 40, 10), dbg!(25, 30, 20))); dia!(choice!( dbg!(10, 15, 10), dbg!(10, 15, 5), dbg!(20, 35, 22), dbg!(10, 15, 10) )); dia!(choice!(Empty, dbg!(5, 20, 10), dbg!(25, 35, 5))); hr!(); // Vertical grid raw_dia!(vert!( seq!(SimpleStart, term!("42"), SimpleEnd), cmt!("This is the answer") )); raw_dia!(vert!( seq!(SimpleStart, dbg!(15, 40, 10), SimpleEnd), seq!(Start, dbg!(25, 35, 5), End) )); hr!(); // Horizontal grid raw_dia!(horiz!( seq!(SimpleStart, term!("42"), SimpleEnd), cmt!("This is the answer") )); raw_dia!(horiz!( seq!(SimpleStart, dbg!(15, 40, 10), SimpleEnd), seq!(Start, dbg!(25, 35, 5), End) )); hr!(); // LabeledBox dia!(lbox!(term!("Foo"), term!("Bar!"))); dia!(choice!( lbox!(Empty, cmt!("Do nothing")), lbox!(term!("bar"), cmt!("Do something")) )); hr!(); // Repeats dia!(rpt!(Empty, Empty)); dia!(rpt!(dbg!(20, 30, 10), dbg!(30, 50, 20))); dia!(rpt!(dbg!(5, 15, 10), dbg!(5, 15, 20))); dia!(rpt!(nonterm!("Foo"), term!(","))); dia!(rpt!( cmt!("<-- this is longer -->"), cmt!("this is shorter") )); dia!(rpt!( nonterm!("Foo"), lbox!(term!(","), cmt!("A comment that runs long")) )); dia!(rpt!( cmt!("this is shorter"), cmt!("<-- this is longer -->") )); hr!(); // Stacks dia!(stck!()); dia!(stck!(Empty)); dia!(stck!(Empty, Empty)); dia!(stck!(Empty, dbg!(5, 25, 10))); dia!(stck!(dbg!(15, 40, 10), dbg!(25, 30, 20))); dia!(stck!( dbg!(10, 15, 10), dbg!(10, 15, 5), seq!(dbg!(), dbg!(20, 35, 22)), dbg!(10, 15, 10) )); hr!(); // Links dia!(lnk!(term!("www.rust-lang.org"))); dia!({ let mut l = lnk!(term!("www.rust-lang.org")); l.set_target(Some(LinkTarget::Blank)); l }); hr!(); dia!(choice!( rpt!( seq!( choice!( term!("Foo"), seq!(opt!(term!("BarNoodle")), term!("NoodleBox"), term!("foo")), term!("More"), term!("42") ), stck!( nonterm!("Stack1"), opt!(nonterm!("Stack2")), nonterm!("Stack2"), opt!(nonterm!("Stack4")) ) ), term!(",") ), rpt!(term!("x"), cmt!("1-6 times")) )); hr!(); dia!(stck!( seq!( term!("ALTER"), term!("TABLE"), opt!(seq!(term!("schema-name"), term!("."))), term!("table-name") ), lbox!( choice!( lbox!( seq!(term!("RENAME"), term!("TO"), term!("new-table-name")), cmt!("Wow") ), seq!(term!("ADD"), opt!(term!("COLUMN")), nonterm!("column-def")) ), cmt!("Foo") ) )); hr!(); dia!(opt!(choice!( seq!(term!("ON"), nonterm!("expr")), seq!( term!("USING"), term!("("), rpt!(term!("column-name"), term!(",")), term!(")") ) ))); hr!(); dia!(seq!( nonterm!("$i:expr"), term!(","), choice!( seq!( nonterm!("$submac:ident"), term!("!("), opt!(rpt!(nonterm!("$args:tt"), Empty)), term!(")") ), nonterm!("$f:expr") ) )); hr!(); dia!(choice!( cmt!("Macro-internal"), seq!( nonterm!("$i:expr"), term!(","), choice!( seq!( nonterm!("$submac:ident"), term!("!"), lbox!(seq!( term!("("), opt!(rpt!(nonterm!("$args:tt"))), term!(")") )), term!(",") ), nonterm!("$f:expr") ), nonterm!("$g:expr") ) )); hr!(); f.write_all(b"").unwrap(); }