mirror of
				https://git.proxmox.com/git/rustc
				synced 2025-11-04 07:17:58 +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(unused_tuple_struct_fields)]
 | 
						|
enum HTMLFragment {
 | 
						|
    tag(String, Vec<HTMLFragment> ),
 | 
						|
    text(String),
 | 
						|
}
 |