33namespace pegtl = tao::pegtl;
39 template<
int TableVal>
struct lookup_char {
40 using analyze_t = pegtl::analysis::generic<pegtl::analysis::rule_type::ANY>;
41 template<
typename Input>
static bool match(
Input&
in) {
46 in.bump_in_this_line(1);
62 struct nonblank_ch : pegtl::range<'!', '~'> {};
65 struct anyprint_ch : pegtl::ranges<' ', '~', '\t'> {};
69 struct comment : pegtl::if_must<pegtl::one<'#'>, pegtl::until<pegtl::eolf>>{};
70 struct whitespace : pegtl::plus<pegtl::sor<ws_char, comment>> {};
71 struct ws_or_eof : pegtl::sor<whitespace, pegtl::eof> {};
79 struct keyword : pegtl::sor<str_data, str_loop, str_global,
80 str_save, str_stop> {};
84 struct endq : pegtl::seq<Q, pegtl::at<pegtl::sor<
85 pegtl::one<' ','\n','\r','\t','#'>,
91 struct quoted_tail : pegtl::until<endq<Q>, pegtl::not_one<'\n'>> {};
93 struct quoted : pegtl::if_must<Q, quoted_tail<Q>> {};
94 struct singlequoted : quoted<pegtl::one<'\''>> {};
95 struct doublequoted : quoted<pegtl::one<'"'>> {};
96 struct field_sep : pegtl::seq<pegtl::bol, pegtl::one<';'>> {};
99 struct textfield : pegtl::if_must<field_sep, pegtl::until<field_sep>> {};
100 struct unquoted : pegtl::seq<pegtl::not_at<keyword>,
101 pegtl::not_at<pegtl::one<'_','$','#'>>,
102 pegtl::plus<nonblank_ch>> {};
107 struct datablockname : pegtl::star<nonblank_ch> {};
108 struct datablockheading : pegtl::sor<pegtl::seq<str_data, datablockname>, str_global> {};
109 struct tag : pegtl::seq<pegtl::one<'_'>, pegtl::plus<nonblank_ch>> {};
112 struct simunq : pegtl::seq<pegtl::plus<ordinary_char>, pegtl::at<ws_char>> {};
113 struct value : pegtl::sor<simunq, singlequoted, doublequoted,
114 textfield, unquoted> {};
115 struct item_tag : tag {};
116 struct item_value : value {};
117 struct loop_tag : tag {};
118 struct loop_value : value {};
119 struct loop_end : pegtl::opt<str_stop, ws_or_eof> {};
120 struct loop : pegtl::if_must<str_loop,
122 pegtl::plus<pegtl::seq<loop_tag, whitespace, pegtl::discard>>,
123 pegtl::sor<pegtl::plus<pegtl::seq<loop_value, ws_or_eof,
126 pegtl::at<pegtl::sor<keyword, pegtl::eof>>>,
128 struct missing_value : pegtl::bol {};
129 struct dataitem : pegtl::if_must<item_tag, whitespace,
130 pegtl::if_then_else<item_value, ws_or_eof,
133 struct framename : pegtl::plus<nonblank_ch> {};
134 struct endframe : str_save {};
135 struct frame : pegtl::if_must<str_save, framename, whitespace,
136 pegtl::star<pegtl::sor<dataitem, loop>>,
137 endframe, ws_or_eof> {};
138 struct datablock : pegtl::seq<datablockheading, ws_or_eof,
139 pegtl::star<pegtl::sor<dataitem, loop, frame>>> {};
140 struct content : pegtl::plus<datablock> {};
141 struct file : pegtl::seq<pegtl::opt<whitespace>,
142 pegtl::if_must<pegtl::not_at<pegtl::eof>,
143 content, pegtl::eof>> {};
144 struct one_block : pegtl::seq<pegtl::opt<whitespace>,
145 pegtl::if_must<pegtl::not_at<pegtl::eof>, datablock>> {};
154 static const std::string s =
"parse error";
157#define error_msg(rule, msg) \
158 template<> inline const std::string& error_message<rule>() { \
159 static const std::string s = msg; \
162error_msg(rules::quoted_tail<pegtl::one<
'\''>>,
"unterminated 'string'")
163error_msg(rules::quoted_tail<pegtl::one<'"'>>, "unterminated \"
string\"")
164error_msg(pegtl::until<rules::field_sep>, "unterminated text field")
165error_msg(rules::framename, "unnamed save_ frame")
166error_msg(rules::content, "expected block header (data_)")
169template<
typename Rule>
struct Errors :
public pegtl::normal<Rule> {
170 template<
typename Input,
typename ... States>
171 static void raise(
const Input& in, States&& ...) {
172 throw pegtl::parse_error(error_message<Rule>()
180template<
typename Rule>
struct Action : pegtl::nothing<Rule> {};
194template<>
struct Action<rules::datablockname> {
195 template<
typename Input>
static void apply(
const Input& in, Document& out) {
196 out.blocks.emplace_back(in.string());
197 Block& block = out.blocks.back();
200 if (block.name.empty())
202 out.items_ = &block.items;
205template<>
struct Action<rules::str_global> {
206 template<
typename Input>
static void apply(
const Input&, Document& out) {
207 out.blocks.emplace_back();
208 out.items_ = &out.blocks.back().items;
211template<>
struct Action<rules::framename> {
212 template<
typename Input>
static void apply(
const Input& in, Document& out) {
213 out.items_->emplace_back(FrameArg{in.string()});
214 out.items_->back().line_number = in.iterator().line;
215 out.items_ = &out.items_->back().frame.items;
218template<>
struct Action<rules::endframe> {
219 template<
typename Input>
static void apply(
const Input&, Document& out) {
220 out.items_ = &out.blocks.back().items;
223template<>
struct Action<rules::item_tag> {
224 template<
typename Input>
static void apply(
const Input& in, Document& out) {
225 out.items_->emplace_back(in.string());
226 out.items_->back().line_number = in.iterator().line;
229template<>
struct Action<rules::item_value> {
230 template<
typename Input>
static void apply(
const Input& in, Document& out) {
231 Item& last_item = out.items_->back();
233 last_item.pair[1] = in.string();
236template<>
struct Action<rules::str_loop> {
237 template<
typename Input>
static void apply(
const Input& in, Document& out) {
238 out.items_->emplace_back(LoopArg{});
239 out.items_->back().line_number = in.iterator().line;
242template<>
struct Action<rules::loop_tag> {
243 template<
typename Input>
static void apply(
const Input& in, Document& out) {
244 Item& last_item = out.items_->back();
246 last_item.loop.tags.emplace_back(in.string());
249template<>
struct Action<rules::loop_value> {
250 template<
typename Input>
static void apply(
const Input& in, Document& out) {
251 Item& last_item = out.items_->back();
253 last_item.loop.values.emplace_back(in.string());
256template<>
struct Action<rules::loop> {
257 template<
typename Input>
static void apply(
const Input& in, Document& out) {
258 Item& last_item = out.items_->back();
260 const Loop& loop = last_item.loop;
261 if (loop.values.size() % loop.tags.size() != 0)
262 throw pegtl::parse_error(
263 "Wrong number of values in loop " + loop.common_prefix() +
"*",
270 pegtl::parse<rules::file, Action, Errors>(
in,
d);
275 doc.source =
in.source();
282template<
typename Input>
284 pegtl::parse<rules::one_block, Action, Errors>(
in,
d);
291#define GEMMI_CIF_FILE_INPUT(in, path) \
292 tao::pegtl::read_input<> in(gemmi::file_open(path.c_str(), "rb").release(), path)
294#define GEMMI_CIF_FILE_INPUT(in, path) \
295 tao::pegtl::file_input<> in(path)
304 pegtl::memory_input<>
in(data,
"string");
309 pegtl::memory_input<>
in(data, size, name);
314 pegtl::cstream_input<>
in(f,
bufsize, name);
319 size_t bufsize,
const char* name) {
325template<
typename Rule>
struct CheckAction : pegtl::nothing<Rule> {};
327template<>
struct CheckAction<rules::missing_value> {
328 template<
typename Input>
static void apply(
const Input& in) {
329 throw pegtl::parse_error(
"tag without value", in);
335 return pegtl::parse<rules::file, CheckAction, Errors>(
in);
336 }
catch (pegtl::parse_error&
e) {
347 if (
input.is_stdin())
357 pegtl::memory_input<>
in(
mem.data(),
mem.size(),
input.path());
366 if (
input.is_stdin())
368 if (
input.is_compressed()) {
371 input.path().c_str()));