]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/html-literals.rs
5141be1f178b331b05025f3cd45d21fbdbe72702
[rust.git] / src / test / run-pass / html-literals.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // A test of the macro system. Can we do HTML literals?
12
13 #[feature(macro_rules)];
14
15 /*
16
17 This is an HTML parser written as a macro. It's all CPS, and we have
18 to carry around a bunch of state. The arguments to macros all look like this:
19
20 { tag_stack* # expr* # tokens }
21
22 The stack keeps track of where we are in the tree. The expr is a list
23 of children of the current node. The tokens are everything that's
24 left.
25
26 */
27
28 macro_rules! html (
29     ( $($body:tt)* ) => (
30         parse_node!( []; []; $($body)* )
31     )
32 )
33
34 macro_rules! parse_node (
35     (
36         [:$head:ident ($(:$head_nodes:expr),*)
37          $(:$tags:ident ($(:$tag_nodes:expr),*))*];
38         [$(:$nodes:expr),*];
39         </$tag:ident> $($rest:tt)*
40     ) => (
41         parse_node!(
42             [$(: $tags ($(:$tag_nodes),*))*];
43             [$(:$head_nodes,)* :tag(stringify!($head).to_owned(),
44                                     vec!($($nodes),*))];
45             $($rest)*
46         )
47     );
48
49     (
50         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
51         [$(:$nodes:expr),*];
52         <$tag:ident> $($rest:tt)*
53     ) => (
54         parse_node!(
55             [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*];
56             [];
57             $($rest)*
58         )
59     );
60
61     (
62         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
63         [$(:$nodes:expr),*];
64         . $($rest:tt)*
65     ) => (
66         parse_node!(
67             [$(: $tags ($(:$tag_nodes),*))*];
68             [$(:$nodes,)* :text(~".")];
69             $($rest)*
70         )
71     );
72
73     (
74         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
75         [$(:$nodes:expr),*];
76         $word:ident $($rest:tt)*
77     ) => (
78         parse_node!(
79             [$(: $tags ($(:$tag_nodes),*))*];
80             [$(:$nodes,)* :text(stringify!($word).to_owned())];
81             $($rest)*
82         )
83     );
84
85     ( []; [:$e:expr]; ) => ( $e );
86 )
87
88 pub fn main() {
89     let _page = html! (
90         <html>
91             <head><title>This is the title.</title></head>
92             <body>
93             <p>This is some text</p>
94             </body>
95         </html>
96     );
97 }
98
99 enum HTMLFragment {
100     tag(~str, Vec<HTMLFragment> ),
101     text(~str),
102 }