]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | // run-pass |
2 | ||
0bf4aa26 | 3 | #![allow(non_camel_case_types)] |
223e47cc LB |
4 | // A test of the macro system. Can we do HTML literals? |
5 | ||
223e47cc LB |
6 | /* |
7 | ||
8 | This is an HTML parser written as a macro. It's all CPS, and we have | |
9 | to carry around a bunch of state. The arguments to macros all look like this: | |
10 | ||
11 | { tag_stack* # expr* # tokens } | |
12 | ||
13 | The stack keeps track of where we are in the tree. The expr is a list | |
14 | of children of the current node. The tokens are everything that's | |
15 | left. | |
16 | ||
17 | */ | |
1a4d82fc | 18 | use HTMLFragment::{tag, text}; |
223e47cc | 19 | |
1a4d82fc | 20 | macro_rules! html { |
223e47cc LB |
21 | ( $($body:tt)* ) => ( |
22 | parse_node!( []; []; $($body)* ) | |
23 | ) | |
1a4d82fc | 24 | } |
223e47cc | 25 | |
1a4d82fc | 26 | macro_rules! parse_node { |
223e47cc LB |
27 | ( |
28 | [:$head:ident ($(:$head_nodes:expr),*) | |
29 | $(:$tags:ident ($(:$tag_nodes:expr),*))*]; | |
30 | [$(:$nodes:expr),*]; | |
31 | </$tag:ident> $($rest:tt)* | |
32 | ) => ( | |
33 | parse_node!( | |
34 | [$(: $tags ($(:$tag_nodes),*))*]; | |
1a4d82fc | 35 | [$(:$head_nodes,)* :tag(stringify!($head).to_string(), |
c30ab7b3 | 36 | vec![$($nodes),*])]; |
223e47cc LB |
37 | $($rest)* |
38 | ) | |
39 | ); | |
40 | ||
41 | ( | |
42 | [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; | |
43 | [$(:$nodes:expr),*]; | |
44 | <$tag:ident> $($rest:tt)* | |
45 | ) => ( | |
46 | parse_node!( | |
47 | [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*]; | |
48 | []; | |
49 | $($rest)* | |
50 | ) | |
51 | ); | |
52 | ||
53 | ( | |
54 | [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; | |
55 | [$(:$nodes:expr),*]; | |
56 | . $($rest:tt)* | |
57 | ) => ( | |
58 | parse_node!( | |
59 | [$(: $tags ($(:$tag_nodes),*))*]; | |
1a4d82fc | 60 | [$(:$nodes,)* :text(".".to_string())]; |
223e47cc LB |
61 | $($rest)* |
62 | ) | |
63 | ); | |
64 | ||
65 | ( | |
66 | [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; | |
67 | [$(:$nodes:expr),*]; | |
68 | $word:ident $($rest:tt)* | |
69 | ) => ( | |
70 | parse_node!( | |
71 | [$(: $tags ($(:$tag_nodes),*))*]; | |
1a4d82fc | 72 | [$(:$nodes,)* :text(stringify!($word).to_string())]; |
223e47cc LB |
73 | $($rest)* |
74 | ) | |
75 | ); | |
76 | ||
77 | ( []; [:$e:expr]; ) => ( $e ); | |
1a4d82fc | 78 | } |
223e47cc LB |
79 | |
80 | pub fn main() { | |
1a4d82fc | 81 | let _page = html! ( |
223e47cc LB |
82 | <html> |
83 | <head><title>This is the title.</title></head> | |
84 | <body> | |
85 | <p>This is some text</p> | |
86 | </body> | |
87 | </html> | |
88 | ); | |
89 | } | |
90 | ||
91 | enum HTMLFragment { | |
1a4d82fc JJ |
92 | tag(String, Vec<HTMLFragment> ), |
93 | text(String), | |
223e47cc | 94 | } |