49 namespace parameter_substitution {
51 string specifier::legible()
const
54 s += to_string(get_param_index());
56 switch(get_handling()) {
57 case handling::substitute_arg:
60 case handling::substitute_expanded_arg:
63 case handling::substitute_quoted_arg:
72 ptrdiff_t format::adjust_for_stringify_op(
size_t pos,
size_t nparams)
75 if (++pos >= _fmt.length() ||
76 (pos += bool(isspace(_fmt[pos]))) >= _fmt.length()) {
81 auto found = specifier::get_at(_fmt,pos,i_off,h_off);
82 if (found != string::npos) {
83 _fmt[h_off] = char(handling::substitute_quoted_arg);
84 _fmt.erase(mark,pos - mark);
92 ptrdiff_t format::adjust_for_token_paste_op(
size_t pos)
96 while (--p >= 0 && isspace(_fmt[p])){}
103 if (specifier::get_ending_at(_fmt,pos,i_off,h_off) != string::npos) {
104 _fmt[h_off] = char(handling::substitute_arg);
108 size_t start_cut = pos + 1;
110 for ( ;pos < _fmt.length() && isspace(_fmt[pos]); ++pos){}
111 if (pos >= _fmt.length()) {
114 if (specifier::get_at(_fmt,pos,i_off,h_off) != string::npos) {
115 _fmt[h_off] = char(handling::substitute_arg);
119 size_t cut_len = pos - start_cut;
120 _fmt.erase(start_cut,cut_len);
124 void format::do_stringify_adjustments(
size_t nparams)
126 ptrdiff_t netdiff = 0;
127 for (
size_t pos: _stringify_offs) {
128 netdiff += adjust_for_stringify_op(pos + netdiff,nparams);
132 void format::do_token_paste_adjustments()
134 ptrdiff_t netdiff = 0;
135 for (
size_t pos: _token_paste_offs) {
136 netdiff += adjust_for_token_paste_op(pos + netdiff);
140 void format::build_format(
symbol & sym)
142 string & s =
const_cast<string &
>(*sym.
defn());
146 auto mark = size_t(chew);
147 size_t diff = mark - _fmt.length();
149 if (
size_t(chew) > mark) {
150 _fmt += s.substr(mark,
size_t(chew) - mark);
157 if (
size_t(chew) > mark) {
158 if (!_fmt.size() || _fmt.back() !=
' ') {
168 if (++chew && *chew ==
'#') {
170 _token_paste_offs.push_back(mark - diff);
174 _stringify_offs.push_back(mark - diff);
178 if (
size_t(chew) == mark) {
183 string id = s.substr(mark,
size_t(chew) - mark);
184 size_t param_i = params.
which(
id);
185 if (param_i != string::npos) {
186 specifier spec(param_i,handling::substitute_expanded_arg);
187 spec.append_to(_fmt);
193 do_stringify_adjustments(params.
size());
194 do_token_paste_adjustments();
197 format::format(
symbol & sym)
206 gripe <<
"#-operator must precede a macro parameter in definition >>"
210 gripe <<
"##-operator cannot begin or end the definition >>"
214 gripe <<
"##-operator does not compose a token in definition >>"
219 std::string format::legible(
string const & str)
222 chewer<string> chew(chew_mode::plaintext,const_cast<string &>(str));
224 size_t mark = size_t(chew);
226 if (
size_t(chew) > mark) {
227 s += str.substr(mark,
size_t(chew) - mark);
240 std::string format::legible()
const
std::string signature() const
Get the symbol's reference signature as string.
template struct error_msg<Id> generically encapsulates an error diagnostic.
error_msg< 24 > error_misplaced_token_paste
Report a ## operator at start or end of definition.
std::shared_ptr< std::string const > defn() const
Get a pointer to the symbol's definition; null if undefined.
size_t size() const
Get the number of parameters in the parameter_list_base
chew_mode::whitespace const whitespace
An exemplar chew_mode::whitespace
formal_parameter_list const & parameters() const
Get the symbol's formal parameter list.
std::string read(chewer< CharSeq > &chew)
Read an identifier from an chewer<CharSeq>
chew_mode::name const name
An exemplar chew_mode::name
The tag class is inserted in a diagnostic_base to tell it to emit itself.
error_msg< 27 > error_bad_token_paste
Report that token-pasting does not yield a token.
bool is_valid_char(char ch)
Say whether a character can occur in an identifier.
`template struct chewer<CharSeq> is a cursor-like type that is associated with a character-sequence t...
struct symbol encapsulates a preprocessor symbol's state
size_t which(std::string const &str) const
Get the index of the parameter that matches a string, if any, else -1.
error_msg< 25 > error_stringify_non_param
Report a # operator not preceding a parameter for function-like macro.
chew_mode::literal_space const literal_space
An exemplar chew_mode::literal_space