2019-07-27 00:54:25 +03:00
|
|
|
// run-pass
|
|
|
|
|
2018-09-14 12:20:28 +02:00
|
|
|
#![allow(non_camel_case_types)]
|
2012-08-09 16:48:31 -07:00
|
|
|
// A test of the macro system. Can we do HTML literals?
|
|
|
|
|
2012-08-10 11:48:09 -07:00
|
|
|
/*
|
|
|
|
|
|
|
|
This is an HTML parser written as a macro. It's all CPS, and we have
|
|
|
|
to carry around a bunch of state. The arguments to macros all look like this:
|
|
|
|
|
|
|
|
{ tag_stack* # expr* # tokens }
|
|
|
|
|
|
|
|
The stack keeps track of where we are in the tree. The expr is a list
|
|
|
|
of children of the current node. The tokens are everything that's
|
|
|
|
left.
|
|
|
|
|
|
|
|
*/
|
2014-11-06 00:05:53 -08:00
|
|
|
use HTMLFragment::{tag, text};
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2015-01-02 14:44:21 -08:00
|
|
|
macro_rules! html {
|
2012-08-22 18:06:54 -07:00
|
|
|
( $($body:tt)* ) => (
|
2012-08-10 11:48:09 -07:00
|
|
|
parse_node!( []; []; $($body)* )
|
|
|
|
)
|
2015-01-02 14:44:21 -08:00
|
|
|
}
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2015-01-02 14:44:21 -08:00
|
|
|
macro_rules! parse_node {
|
2012-08-22 18:06:54 -07:00
|
|
|
(
|
2012-08-10 11:48:09 -07:00
|
|
|
[:$head:ident ($(:$head_nodes:expr),*)
|
|
|
|
$(:$tags:ident ($(:$tag_nodes:expr),*))*];
|
|
|
|
[$(:$nodes:expr),*];
|
|
|
|
</$tag:ident> $($rest:tt)*
|
2012-08-22 18:06:54 -07:00
|
|
|
) => (
|
2012-08-10 11:48:09 -07:00
|
|
|
parse_node!(
|
|
|
|
[$(: $tags ($(:$tag_nodes),*))*];
|
2014-05-25 03:17:19 -07:00
|
|
|
[$(:$head_nodes,)* :tag(stringify!($head).to_string(),
|
2016-10-29 22:54:04 +01:00
|
|
|
vec![$($nodes),*])];
|
2012-08-10 11:48:09 -07:00
|
|
|
$($rest)*
|
|
|
|
)
|
|
|
|
);
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2012-08-22 18:06:54 -07:00
|
|
|
(
|
2012-08-10 11:48:09 -07:00
|
|
|
[$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
|
|
|
|
[$(:$nodes:expr),*];
|
|
|
|
<$tag:ident> $($rest:tt)*
|
2012-08-22 18:06:54 -07:00
|
|
|
) => (
|
2012-08-10 11:48:09 -07:00
|
|
|
parse_node!(
|
|
|
|
[:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*];
|
|
|
|
[];
|
|
|
|
$($rest)*
|
|
|
|
)
|
|
|
|
);
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2012-08-22 18:06:54 -07:00
|
|
|
(
|
2012-08-10 11:48:09 -07:00
|
|
|
[$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
|
|
|
|
[$(:$nodes:expr),*];
|
|
|
|
. $($rest:tt)*
|
2012-08-22 18:06:54 -07:00
|
|
|
) => (
|
2012-08-10 11:48:09 -07:00
|
|
|
parse_node!(
|
|
|
|
[$(: $tags ($(:$tag_nodes),*))*];
|
2014-05-25 03:17:19 -07:00
|
|
|
[$(:$nodes,)* :text(".".to_string())];
|
2012-08-10 11:48:09 -07:00
|
|
|
$($rest)*
|
|
|
|
)
|
|
|
|
);
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2012-08-22 18:06:54 -07:00
|
|
|
(
|
2012-08-10 11:48:09 -07:00
|
|
|
[$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
|
|
|
|
[$(:$nodes:expr),*];
|
|
|
|
$word:ident $($rest:tt)*
|
2012-08-22 18:06:54 -07:00
|
|
|
) => (
|
2012-08-10 11:48:09 -07:00
|
|
|
parse_node!(
|
|
|
|
[$(: $tags ($(:$tag_nodes),*))*];
|
2014-05-25 03:17:19 -07:00
|
|
|
[$(:$nodes,)* :text(stringify!($word).to_string())];
|
2012-08-10 11:48:09 -07:00
|
|
|
$($rest)*
|
|
|
|
)
|
|
|
|
);
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2012-08-22 18:06:54 -07:00
|
|
|
( []; [:$e:expr]; ) => ( $e );
|
2015-01-02 14:44:21 -08:00
|
|
|
}
|
2012-08-09 16:48:31 -07:00
|
|
|
|
2013-02-01 19:43:17 -08:00
|
|
|
pub fn main() {
|
2013-08-17 08:37:42 -07:00
|
|
|
let _page = html! (
|
2012-08-09 16:48:31 -07:00
|
|
|
<html>
|
|
|
|
<head><title>This is the title.</title></head>
|
|
|
|
<body>
|
|
|
|
<p>This is some text</p>
|
|
|
|
</body>
|
|
|
|
</html>
|
2012-08-22 17:24:52 -07:00
|
|
|
);
|
2012-08-09 16:48:31 -07:00
|
|
|
}
|
|
|
|
|
2022-07-25 22:36:03 +02:00
|
|
|
#[allow(unused_tuple_struct_fields)]
|
2012-08-10 11:48:09 -07:00
|
|
|
enum HTMLFragment {
|
2014-05-22 16:57:53 -07:00
|
|
|
tag(String, Vec<HTMLFragment> ),
|
|
|
|
text(String),
|
2012-08-09 16:48:31 -07:00
|
|
|
}
|