mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 13:04:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			96 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //@ run-pass
 | |
| 
 | |
| #![allow(non_camel_case_types)]
 | |
| // A test of the macro system. Can we do HTML literals?
 | |
| 
 | |
| /*
 | |
| 
 | |
| 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.
 | |
| 
 | |
| */
 | |
| use HTMLFragment::{tag, text};
 | |
| 
 | |
| macro_rules! html {
 | |
|     ( $($body:tt)* ) => (
 | |
|         parse_node!( []; []; $($body)* )
 | |
|     )
 | |
| }
 | |
| 
 | |
| macro_rules! parse_node {
 | |
|     (
 | |
|         [:$head:ident ($(:$head_nodes:expr),*)
 | |
|          $(:$tags:ident ($(:$tag_nodes:expr),*))*];
 | |
|         [$(:$nodes:expr),*];
 | |
|         </$tag:ident> $($rest:tt)*
 | |
|     ) => (
 | |
|         parse_node!(
 | |
|             [$(: $tags ($(:$tag_nodes),*))*];
 | |
|             [$(:$head_nodes,)* :tag(stringify!($head).to_string(),
 | |
|                                     vec![$($nodes),*])];
 | |
|             $($rest)*
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     (
 | |
|         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
 | |
|         [$(:$nodes:expr),*];
 | |
|         <$tag:ident> $($rest:tt)*
 | |
|     ) => (
 | |
|         parse_node!(
 | |
|             [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*];
 | |
|             [];
 | |
|             $($rest)*
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     (
 | |
|         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
 | |
|         [$(:$nodes:expr),*];
 | |
|         . $($rest:tt)*
 | |
|     ) => (
 | |
|         parse_node!(
 | |
|             [$(: $tags ($(:$tag_nodes),*))*];
 | |
|             [$(:$nodes,)* :text(".".to_string())];
 | |
|             $($rest)*
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     (
 | |
|         [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
 | |
|         [$(:$nodes:expr),*];
 | |
|         $word:ident $($rest:tt)*
 | |
|     ) => (
 | |
|         parse_node!(
 | |
|             [$(: $tags ($(:$tag_nodes),*))*];
 | |
|             [$(:$nodes,)* :text(stringify!($word).to_string())];
 | |
|             $($rest)*
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     ( []; [:$e:expr]; ) => ( $e );
 | |
| }
 | |
| 
 | |
| pub fn main() {
 | |
|     let _page = html! (
 | |
|         <html>
 | |
|             <head><title>This is the title.</title></head>
 | |
|             <body>
 | |
|             <p>This is some text</p>
 | |
|             </body>
 | |
|         </html>
 | |
|     );
 | |
| }
 | |
| 
 | |
| #[allow(dead_code)]
 | |
| enum HTMLFragment {
 | |
|     tag(String, Vec<HTMLFragment> ),
 | |
|     text(String),
 | |
| }
 | 
