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