Я не думаю, что есть ярлык, вы должны указать грамматику таким образом, чтобы было однозначно, где и сколько пробелов вы допускаете.
Лучший способ сделать это, я думаю, этодобавьте удобный шаблон правил, который позволяет сопоставлять список (tao::pegtl::seq
) правил, разделенных любым разрешенным разделителем (обычно пробел плюс комментарии).
struct comment : tao::pegtl::disable< /* whatever your comment syntax is */ > {};
struct separator : tao::pegtl::sor< tao::pegtl::ascii::space, comment > {}; // either/or
struct seps : tao::pegtl::star< separator > {}; // Any separators, whitespace or comments
// Template to generate rule
// tao::pegtl::seq<Rule0, Separator, Rule1, Separator, Rule2, ... , Separator, RuleN>
template <typename Separator, typename... Rules>
struct interleaved;
template <typename Separator, typename Rule0, typename... RulesRest>
struct interleaved<Separator, Rule0, RulesRest...>
: tao::pegtl::seq<Rule0, Separator, interleaved<Separator, RulesRest...>> {};
template <typename Separator, typename Rule0>
struct interleaved<Separator, Rule0>
: Rule0 {};
// Note: interleaved<Separator /*, no Rule! */> intentionally not defined.
struct enum_decl : interleaved<seps, kw_enum, tao::pegtl::identifier, tao::pegtl::one<';'> {};
// Expands to:
seq<kw_enum, seps, interleaved<seps, identifier, one<';'>>> ==
seq<kw_enum, seps, seq<identifier, seps, interleaved<seps, one<';'>>>> ==
seq<kw_enum, seps, seq<identifier, seps, one<';'>> ==
seq<kw_enum, seps, identifier, seps, one<';'>>
По существу, выполняется что-то вродевыше, вам нужно всего лишь заменить tao::pegtl::seq<R...>
на interleaved<seps, R...>
, но вы можете даже создать отдельный псевдоним для этого:
template<typename... Rules>
using sseq = interleaved<seps, Rules...>;
// Now you only have to replace tao::pegtl::seq with sseq
struct enum_decl : sseq<kw_enum, tao::pegtl::identifier, tao::pegtl::one<';'>> {};
Эта стратегия в основном нужна не из-за значимых пробелов языков, а потому, что вынет более раннего шага токенизатора при разборе, который бы отделял enum
от thing
.Другая стратегия заключалась бы в том, чтобы реализовать это вначале и выполнить последующий анализ на основе потока токенов вместо потока символов, но это большая перезапись и имеет свои недостатки.
Примечание: я не скомпилировал код, но суть здесь должна быть в стратегии.Пожалуйста, оставьте комментарий, если есть ошибка компиляции (я надеюсь, что я не испортил вариационные шаблоны) или если что-то неясно.
Примечание 2. Также вы, вероятно, не хотите заменять каждый seq
с sseq
.Например, если у вас есть логические и (&&
), определенные как seq<one<'&'>, one<'&'>>
, это то, что вы, вероятно, не хотите менять.