-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathhtml.cpp
117 lines (101 loc) · 2.98 KB
/
html.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
HTML parser
It only deals with matching tags parsing for simplification.
Texts and attributes are a trivial task to add
This example shows how to take advantage of the fact that the parser is defined in c++.
Here both terms and rules are generated from tag names
*/
#include <ctpg/ctpg.hpp>
#include <iostream>
#include <vector>
using namespace ctpg;
using namespace ctpg::ftors;
using namespace ctpg::buffers;
class html_block;
using list_type = std::vector<html_block>;
class html_block
{
public:
html_block(std::string_view tag, list_type&& list):
name(tag), inner_blocks(std::move(list))
{}
private:
std::string name;
list_type inner_blocks;
};
template<std::size_t N>
struct tag
{
constexpr tag(const char (&name)[N])
{
open_tag_str[0] = '<';
for (auto i = 0u; i < N - 1; ++i) // skip terminating 0
open_tag_str[i + 1] = name[i];
open_tag_str[N] = '>';
close_tag_str[0] = '<';
close_tag_str[1] = '/';
for (auto i = 0u; i < N - 1; ++i) // skip terminating 0
close_tag_str[i + 2] = name[i];
close_tag_str[N + 1] = '>';
}
constexpr const auto& get_open_tag_str() const { return open_tag_str; }
constexpr const auto& get_close_tag_str() const { return close_tag_str; }
char open_tag_str[N + 2] = {0};
char close_tag_str[N + 3] = {0};
};
constexpr auto tag_tuple = std::make_tuple(
tag("div"),
tag("span"),
tag("a"),
tag("button")
);
constexpr nterm<html_block> block("block");
constexpr nterm<list_type> block_list("list");
template<typename Tags>
constexpr auto create_terms(Tags tags)
{
return std::apply(
[](auto... tag)
{
return ctpg::terms(tag.get_open_tag_str()..., tag.get_close_tag_str()...);
},
tags
);
}
template<typename Tags>
constexpr auto create_rules(Tags tags)
{
return std::apply(
[](auto... tag)
{
// create rule in the form:
// block("<tag>" block_list "</tag>") for each tag
// and add last two rules not depending on tags
return ctpg::rules(
block(tag.get_open_tag_str(), block_list, tag.get_close_tag_str())
>= [](auto tag, auto&& list, skip){ return html_block(tag, std::move(list)); }...,
block_list()
>= create<list_type>{},
block_list(block_list, block)
>= [](auto&& list, auto&& block){ list.emplace_back(std::move(block)); return std::move(list); }
);
},
tags
);
}
constexpr parser p(
block, // root
create_terms(tag_tuple), // terms
nterms(block, block_list), // nonterms
create_rules(tag_tuple) // rules
);
int main(int argc, char const *argv[])
{
if (argc != 2)
{
p.write_diag_str(std::cout);
return 0;
}
auto res = p.parse(parse_options{}.set_verbose(), string_buffer(argv[1]), std::cerr);
return 0;
}