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"<hr>").unwrap();
};
}
macro_rules! raw_dia {
($r:expr) => {
let dia = Diagram::with_default_css($r);
writeln!(f, "<div style=\"width: {}px; height: auto; max-width: 100%; max-height: 100%\">{}</div>", 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::<Box<dyn Node>>::new(vec![ $( Box::new($r), )+ ]) } }
macro_rules! choice { ($($r: expr),*) => { Choice::<Box<dyn Node>>::new(vec![ $( Box::new($r), )* ]) } }
macro_rules! multichoice {
( $( [ $($r:expr),* $(,)? ] ),* $(,)? ) => {
MultiChoice::<Box<dyn Node>>::new(vec![
$( vec![ $( Box::new($r) as Box<dyn Node>, )* ], )*
])
}
}
macro_rules! stck { ($($r: expr),*) => { Stack::<Box<dyn Node>>::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<dyn Node>, )+ ]) } }
macro_rules! horiz { ($($r: expr),*) => { HorizontalGrid::new(vec![ $( Box::new($r) as Box<dyn Node>, )+ ]) } }
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"<!DOCTYPE html><html>").unwrap();
f.write_all(
br#"
<head>
<meta charset="utf-8">
<title>Railroad diagram examples</title>
<style type="text/css">
svg.railroad {
border: 1px solid;
margin: 10px;
}
</style>
</head>"#,
)
.unwrap();
dia!(nonterm!("Foo"));
dia!(lbox!(nonterm!("Foo")));
dia!(lbox!(nonterm!("Foo"), cmt!("Read the docs regarding foo!")));
hr!();
dia!(dbg!());
dia!(dbg!(20, 50, 50));
hr!();
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!();
dia!(opt!(dbg!(0, 20, 10)));
dia!(opt!(dbg!(25, 45, 20)));
dia!(opt!(dbg!(30, 50, 50)));
hr!();
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!();
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!();
dia!(multichoice!());
dia!(multichoice!([Empty, dbg!(5, 20, 10), dbg!(25, 35, 5)]));
dia!(multichoice!(
[dbg!(15, 40, 10), dbg!(25, 30, 20)],
[dbg!(20, 35, 15), dbg!(10, 25, 10)]
));
dia!(multichoice!(
[dbg!(10, 15, 10), dbg!(10, 15, 5), dbg!(20, 35, 22)],
[dbg!(30, 45, 20)],
[dbg!(8, 20, 12), dbg!(25, 30, 8)]
));
dia!(multichoice!(
[Empty, dbg!(5, 20, 10)],
[dbg!(25, 35, 5), Empty]
));
dia!(multichoice!(
[dbg!(12, 30, 12), dbg!(12, 30, 120)],
[dbg!(12, 30, 20), dbg!(12, 30, 75)]
));
dia!(multichoice!(
[
seq!(dbg!(20, 30, 10), dbg!(30, 50, 70)),
opt!(dbg!(30, 50, 50))
],
[
stck!(dbg!(10, 15, 10), dbg!(20, 35, 22)),
choice!(dbg!(10, 25, 20), dbg!(18, 35, 20))
]
));
dia!(multichoice!(
[dbg!(12, 30, 45), dbg!(12, 30, 45)],
[dbg!(12, 30, 55), dbg!(12, 30, 55), dbg!(12, 30, 55)],
[dbg!(12, 30, 45), dbg!(12, 30, 45)]
));
dia!(multichoice!(
[dbg!(12, 30, 40)],
[dbg!(12, 30, 35)],
[dbg!(12, 30, 65)],
[dbg!(12, 30, 45)]
));
dia!(multichoice!(
[dbg!(12, 30, 40), dbg!(18, 40, 30)],
[],
[dbg!(10, 25, 55), dbg!(15, 35, 25)]
));
dia!(multichoice!(
[dbg!(12, 30, 35)],
[dbg!(8, 70, 50), dbg!(45, 90, 35)],
[dbg!(16, 35, 40), dbg!(28, 70, 60), dbg!(12, 30, 30)]
));
dia!(multichoice!(
[
dbg!(10, 35, 35),
dbg!(40, 85, 50),
dbg!(12, 30, 25),
dbg!(30, 60, 45)
],
[dbg!(12, 30, 60)]
));
dia!(multichoice!(
[dbg!(28, 60, 55), dbg!(12, 35, 40)],
[dbg!(5, 20, 65), dbg!(12, 30, 45)],
[dbg!(5, 20, 50), dbg!(14, 35, 70)]
));
dia!(multichoice!(
[dbg!(12, 30, 25), dbg!(15, 35, 35)],
[dbg!(20, 45, 150), dbg!(8, 25, 120)],
[dbg!(12, 30, 30), dbg!(18, 45, 20)]
));
dia!(multichoice!(
[dbg!(10, 30, 45), dbg!(20, 45, 30)],
[dbg!(45, 80, 55), dbg!(35, 70, 35)],
[dbg!(50, 95, 65)]
));
dia!(multichoice!(
[dbg!(8, 25, 25), dbg!(18, 45, 40)],
[dbg!(15, 35, 80)],
[dbg!(10, 30, 35), dbg!(25, 60, 45), dbg!(12, 30, 30)],
[dbg!(22, 55, 70), dbg!(8, 25, 20)]
));
hr!();
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!();
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!();
dia!(lbox!(term!("Foo"), term!("Bar!")));
dia!(choice!(
lbox!(Empty, cmt!("Do nothing")),
lbox!(term!("bar"), cmt!("Do something"))
));
hr!();
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!();
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!();
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"</html>").unwrap();
}