about summary refs log tree commit diff
path: root/tests/ui/macros/html-literals.rs
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/macros/html-literals.rs
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/macros/html-literals.rs')
-rw-r--r--tests/ui/macros/html-literals.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/tests/ui/macros/html-literals.rs b/tests/ui/macros/html-literals.rs
new file mode 100644
index 00000000000..26f00fed9c4
--- /dev/null
+++ b/tests/ui/macros/html-literals.rs
@@ -0,0 +1,95 @@
+// 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),
+}