sassc 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/ext/libsass/.gitignore +13 -6
  4. data/ext/libsass/Makefile +42 -26
  5. data/ext/libsass/Makefile.am +43 -30
  6. data/ext/libsass/Readme.md +4 -2
  7. data/ext/libsass/appveyor.yml +10 -14
  8. data/ext/libsass/ast.cpp +54 -44
  9. data/ext/libsass/ast.hpp +404 -236
  10. data/ext/libsass/ast_def_macros.hpp +5 -0
  11. data/ext/libsass/ast_factory.hpp +6 -3
  12. data/ext/libsass/ast_fwd_decl.hpp +12 -0
  13. data/ext/libsass/b64/encode.h +2 -2
  14. data/ext/libsass/backtrace.hpp +13 -17
  15. data/ext/libsass/base64vlq.hpp +4 -1
  16. data/ext/libsass/bind.cpp +12 -15
  17. data/ext/libsass/bind.hpp +6 -6
  18. data/ext/libsass/color_names.hpp +4 -1
  19. data/ext/libsass/configure.ac +7 -21
  20. data/ext/libsass/constants.cpp +6 -4
  21. data/ext/libsass/constants.hpp +10 -4
  22. data/ext/libsass/context.cpp +89 -58
  23. data/ext/libsass/context.hpp +28 -35
  24. data/ext/libsass/contextualize.cpp +20 -10
  25. data/ext/libsass/contextualize.hpp +8 -23
  26. data/ext/libsass/contrib/libsass.spec +66 -0
  27. data/ext/libsass/cssize.cpp +547 -0
  28. data/ext/libsass/cssize.hpp +82 -0
  29. data/ext/libsass/debug.hpp +3 -3
  30. data/ext/libsass/debugger.hpp +358 -0
  31. data/ext/libsass/emitter.cpp +255 -0
  32. data/ext/libsass/emitter.hpp +83 -0
  33. data/ext/libsass/environment.hpp +7 -3
  34. data/ext/libsass/error_handling.cpp +11 -14
  35. data/ext/libsass/error_handling.hpp +9 -7
  36. data/ext/libsass/eval.cpp +253 -161
  37. data/ext/libsass/eval.hpp +13 -13
  38. data/ext/libsass/expand.cpp +135 -64
  39. data/ext/libsass/expand.hpp +11 -13
  40. data/ext/libsass/extend.cpp +66 -20
  41. data/ext/libsass/extend.hpp +6 -11
  42. data/ext/libsass/file.cpp +31 -26
  43. data/ext/libsass/file.hpp +6 -1
  44. data/ext/libsass/functions.cpp +270 -287
  45. data/ext/libsass/functions.hpp +8 -11
  46. data/ext/libsass/inspect.cpp +385 -255
  47. data/ext/libsass/inspect.hpp +15 -26
  48. data/ext/libsass/kwd_arg_macros.hpp +5 -0
  49. data/ext/libsass/mapping.hpp +4 -3
  50. data/ext/libsass/memory_manager.hpp +5 -2
  51. data/ext/libsass/node.cpp +50 -50
  52. data/ext/libsass/node.hpp +26 -27
  53. data/ext/libsass/operation.hpp +15 -4
  54. data/ext/libsass/output.cpp +401 -0
  55. data/ext/libsass/output.hpp +56 -0
  56. data/ext/libsass/parser.cpp +573 -399
  57. data/ext/libsass/parser.hpp +122 -88
  58. data/ext/libsass/paths.hpp +7 -2
  59. data/ext/libsass/plugins.cpp +155 -0
  60. data/ext/libsass/plugins.hpp +56 -0
  61. data/ext/libsass/position.cpp +128 -0
  62. data/ext/libsass/position.hpp +108 -11
  63. data/ext/libsass/prelexer.cpp +184 -110
  64. data/ext/libsass/prelexer.hpp +131 -24
  65. data/ext/libsass/remove_placeholders.cpp +1 -1
  66. data/ext/libsass/remove_placeholders.hpp +6 -6
  67. data/ext/libsass/sass.cpp +3 -3
  68. data/ext/libsass/sass.h +12 -4
  69. data/ext/libsass/sass2scss.cpp +3 -2
  70. data/ext/libsass/sass2scss.h +5 -0
  71. data/ext/libsass/sass_context.cpp +136 -37
  72. data/ext/libsass/sass_context.h +19 -10
  73. data/ext/libsass/sass_functions.cpp +29 -2
  74. data/ext/libsass/sass_functions.h +8 -2
  75. data/ext/libsass/sass_interface.cpp +32 -23
  76. data/ext/libsass/sass_interface.h +9 -4
  77. data/ext/libsass/sass_util.cpp +19 -23
  78. data/ext/libsass/sass_util.hpp +28 -27
  79. data/ext/libsass/sass_values.cpp +6 -4
  80. data/ext/libsass/sass_values.h +3 -3
  81. data/ext/libsass/script/ci-build-libsass +13 -1
  82. data/ext/libsass/script/ci-report-coverage +2 -1
  83. data/ext/libsass/source_map.cpp +79 -28
  84. data/ext/libsass/source_map.hpp +35 -16
  85. data/ext/libsass/subset_map.hpp +6 -4
  86. data/ext/libsass/to_c.hpp +4 -4
  87. data/ext/libsass/to_string.cpp +13 -8
  88. data/ext/libsass/to_string.hpp +6 -4
  89. data/ext/libsass/units.cpp +2 -1
  90. data/ext/libsass/units.hpp +6 -1
  91. data/ext/libsass/utf8_string.cpp +0 -5
  92. data/ext/libsass/utf8_string.hpp +3 -2
  93. data/ext/libsass/util.cpp +461 -49
  94. data/ext/libsass/util.hpp +34 -13
  95. data/ext/libsass/version.sh +10 -0
  96. data/ext/libsass/win/libsass.filters +20 -11
  97. data/ext/libsass/win/libsass.vcxproj +11 -8
  98. data/lib/sassc/importer.rb +1 -8
  99. data/lib/sassc/native.rb +7 -0
  100. data/lib/sassc/native/native_context_api.rb +5 -5
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/native_test.rb +1 -1
  103. metadata +14 -10
  104. data/ext/libsass/copy_c_str.cpp +0 -13
  105. data/ext/libsass/copy_c_str.hpp +0 -5
  106. data/ext/libsass/output_compressed.cpp +0 -401
  107. data/ext/libsass/output_compressed.hpp +0 -95
  108. data/ext/libsass/output_nested.cpp +0 -364
  109. data/ext/libsass/output_nested.hpp +0 -108
  110. data/ext/libsass/test-driver +0 -127
  111. data/ext/libsass/token.hpp +0 -32
@@ -1,29 +1,24 @@
1
- #define SASS_FUNCTIONS
1
+ #ifndef SASS_FUNCTIONS_H
2
+ #define SASS_FUNCTIONS_H
2
3
 
3
4
  #include <string>
4
5
 
5
- #ifndef SASS_ENVIRONMENT
6
- #include "environment.hpp"
7
- #endif
8
-
9
- #ifndef SASS_POSITION
10
6
  #include "position.hpp"
11
- #endif
12
-
7
+ #include "environment.hpp"
13
8
  #include "sass_functions.h"
14
9
 
15
10
  #define BUILT_IN(name) Expression*\
16
- name(Env& env, Env& d_env, Context& ctx, Signature sig, const string& path, Position position, Backtrace* backtrace)
11
+ name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Backtrace* backtrace)
17
12
 
18
13
  namespace Sass {
19
- struct Context;
14
+ class Context;
20
15
  struct Backtrace;
21
16
  class AST_Node;
22
17
  class Expression;
23
18
  class Definition;
24
19
  typedef Environment<AST_Node*> Env;
25
20
  typedef const char* Signature;
26
- typedef Expression* (*Native_Function)(Env&, Env&, Context&, Signature, const string&, Position, Backtrace*);
21
+ typedef Expression* (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*);
27
22
 
28
23
  Definition* make_native_function(Signature, Native_Function, Context&);
29
24
  Definition* make_c_function(Signature sig, Sass_C_Function f, void* cookie, Context& ctx);
@@ -185,3 +180,5 @@ namespace Sass {
185
180
 
186
181
  }
187
182
  }
183
+
184
+ #endif
@@ -1,43 +1,39 @@
1
1
  #include "inspect.hpp"
2
2
  #include "ast.hpp"
3
3
  #include "context.hpp"
4
+ #include "utf8/checked.h"
4
5
  #include <cmath>
6
+ #include <string>
5
7
  #include <iostream>
6
8
  #include <iomanip>
9
+ #include <stdint.h>
10
+ #include <stdint.h>
7
11
 
8
12
  namespace Sass {
9
13
  using namespace std;
10
14
 
11
- Inspect::Inspect(Context* ctx) : buffer(""), indentation(0), ctx(ctx) { }
15
+ Inspect::Inspect(Emitter emi)
16
+ : Emitter(emi)
17
+ { }
12
18
  Inspect::~Inspect() { }
13
19
 
14
20
  // statements
15
21
  void Inspect::operator()(Block* block)
16
22
  {
17
23
  if (!block->is_root()) {
18
- append_to_buffer(" {\n");
19
- ++indentation;
24
+ add_open_mapping(block);
25
+ append_scope_opener();
20
26
  }
27
+ if (output_style() == NESTED) indentation += block->tabs();
21
28
  for (size_t i = 0, L = block->length(); i < L; ++i) {
22
- indent();
23
29
  (*block)[i]->perform(this);
24
- // extra newline at the end of top-level statements
25
- if (block->is_root()) append_to_buffer("\n");
26
- append_to_buffer("\n");
27
30
  }
31
+ if (output_style() == NESTED) indentation -= block->tabs();
28
32
  if (!block->is_root()) {
29
- --indentation;
30
- indent();
31
- append_to_buffer("}");
32
- }
33
- // remove extra newline that gets added after the last top-level block
34
- if (block->is_root()) {
35
- size_t l = buffer.length();
36
- if (l > 2 && buffer[l-1] == '\n' && buffer[l-2] == '\n') {
37
- buffer.erase(l-1);
38
- if (ctx) ctx->source_map.remove_line();
39
- }
33
+ append_scope_closer();
34
+ add_close_mapping(block);
40
35
  }
36
+
41
37
  }
42
38
 
43
39
  void Inspect::operator()(Ruleset* ruleset)
@@ -46,206 +42,288 @@ namespace Sass {
46
42
  ruleset->block()->perform(this);
47
43
  }
48
44
 
45
+ void Inspect::operator()(Keyframe_Rule* rule)
46
+ {
47
+ append_indentation();
48
+ if (rule->rules()) rule->rules()->perform(this);
49
+ rule->block()->perform(this);
50
+ }
51
+
49
52
  void Inspect::operator()(Propset* propset)
50
53
  {
51
54
  propset->property_fragment()->perform(this);
52
- append_to_buffer(": ");
55
+ append_colon_separator();
53
56
  propset->block()->perform(this);
54
57
  }
55
58
 
59
+ void Inspect::operator()(Bubble* bubble)
60
+ {
61
+ append_indentation();
62
+ append_token("Bubble", bubble);
63
+ append_optional_space();
64
+ append_string("(");
65
+ append_optional_space();
66
+ bubble->node()->perform(this);
67
+ append_optional_space();
68
+ append_string(")");
69
+ append_optional_space();
70
+ }
71
+
56
72
  void Inspect::operator()(Media_Block* media_block)
57
73
  {
58
- if (ctx) ctx->source_map.add_mapping(media_block);
59
- append_to_buffer("@media ");
74
+ append_indentation();
75
+ append_token("@media", media_block);
76
+ append_mandatory_space();
77
+ in_media_block = true;
60
78
  media_block->media_queries()->perform(this);
79
+ in_media_block = false;
61
80
  media_block->block()->perform(this);
62
81
  }
63
82
 
64
83
  void Inspect::operator()(Feature_Block* feature_block)
65
84
  {
66
- if (ctx) ctx->source_map.add_mapping(feature_block);
67
- append_to_buffer("@supports ");
85
+ append_indentation();
86
+ append_token("@supports", feature_block);
87
+ append_mandatory_space();
68
88
  feature_block->feature_queries()->perform(this);
69
89
  feature_block->block()->perform(this);
70
90
  }
71
91
 
92
+ void Inspect::operator()(At_Root_Block* at_root_block)
93
+ {
94
+ append_indentation();
95
+ append_token("@at-root ", at_root_block);
96
+ append_mandatory_space();
97
+ if(at_root_block->expression()) at_root_block->expression()->perform(this);
98
+ at_root_block->block()->perform(this);
99
+ }
100
+
72
101
  void Inspect::operator()(At_Rule* at_rule)
73
102
  {
74
- append_to_buffer(at_rule->keyword());
103
+ append_indentation();
104
+ append_token(at_rule->keyword(), at_rule);
75
105
  if (at_rule->selector()) {
76
- append_to_buffer(" ");
106
+ append_mandatory_space();
107
+ in_at_rule = true;
77
108
  at_rule->selector()->perform(this);
109
+ in_at_rule = false;
78
110
  }
79
111
  if (at_rule->block()) {
80
112
  at_rule->block()->perform(this);
81
113
  }
82
114
  else {
83
- append_to_buffer(";");
115
+ append_delimiter();
84
116
  }
85
117
  }
86
118
 
87
119
  void Inspect::operator()(Declaration* dec)
88
120
  {
89
121
  if (dec->value()->concrete_type() == Expression::NULL_VAL) return;
90
- if (ctx) ctx->source_map.add_mapping(dec->property());
122
+ in_declaration = true;
123
+ if (output_style() == NESTED)
124
+ indentation += dec->tabs();
125
+ append_indentation();
91
126
  dec->property()->perform(this);
92
- append_to_buffer(": ");
93
- if (ctx) ctx->source_map.add_mapping(dec->value());
127
+ append_colon_separator();
94
128
  dec->value()->perform(this);
95
- if (dec->is_important()) append_to_buffer(" !important");
96
- append_to_buffer(";");
129
+ if (dec->is_important()) {
130
+ append_optional_space();
131
+ append_string("!important");
132
+ }
133
+ append_delimiter();
134
+ if (output_style() == NESTED)
135
+ indentation -= dec->tabs();
136
+ in_declaration = false;
97
137
  }
98
138
 
99
139
  void Inspect::operator()(Assignment* assn)
100
140
  {
101
- append_to_buffer(assn->variable());
102
- append_to_buffer(": ");
141
+ append_token(assn->variable(), assn);
142
+ append_colon_separator();
103
143
  assn->value()->perform(this);
104
- if (assn->is_guarded()) append_to_buffer(" !default");
105
- append_to_buffer(";");
144
+ if (assn->is_guarded()) {
145
+ append_optional_space();
146
+ append_string("!default");
147
+ }
148
+ append_delimiter();
106
149
  }
107
150
 
108
151
  void Inspect::operator()(Import* import)
109
152
  {
110
153
  if (!import->urls().empty()) {
111
- if (ctx) ctx->source_map.add_mapping(import);
112
- append_to_buffer("@import ");
154
+ append_token("@import", import);
155
+ append_mandatory_space();
156
+
157
+ if (String_Quoted* strq = dynamic_cast<String_Quoted*>(import->urls().front())) {
158
+ strq->is_delayed(false);
159
+ }
160
+
113
161
  import->urls().front()->perform(this);
114
- append_to_buffer(";");
162
+ append_delimiter();
115
163
  for (size_t i = 1, S = import->urls().size(); i < S; ++i) {
116
- append_to_buffer("\n");
117
- if (ctx) ctx->source_map.add_mapping(import);
118
- append_to_buffer("@import ");
164
+ append_mandatory_linefeed();
165
+ append_token("@import", import);
166
+ append_mandatory_space();
167
+
168
+ if (String_Quoted* strq = dynamic_cast<String_Quoted*>(import->urls()[i])) {
169
+ strq->is_delayed(false);
170
+ }
171
+
119
172
  import->urls()[i]->perform(this);
120
- append_to_buffer(";");
173
+ append_delimiter();
121
174
  }
122
175
  }
123
176
  }
124
177
 
125
178
  void Inspect::operator()(Import_Stub* import)
126
179
  {
127
- if (ctx) ctx->source_map.add_mapping(import);
128
- append_to_buffer("@import ");
129
- append_to_buffer(import->file_name());
130
- append_to_buffer(";");
180
+ append_indentation();
181
+ append_token("@import", import);
182
+ append_mandatory_space();
183
+ append_string(import->file_name());
184
+ append_delimiter();
131
185
  }
132
186
 
133
187
  void Inspect::operator()(Warning* warning)
134
188
  {
135
- if (ctx) ctx->source_map.add_mapping(warning);
136
- append_to_buffer("@warn ");
189
+ append_indentation();
190
+ append_token("@warn", warning);
191
+ append_mandatory_space();
137
192
  warning->message()->perform(this);
138
- append_to_buffer(";");
193
+ append_delimiter();
139
194
  }
140
195
 
141
196
  void Inspect::operator()(Error* error)
142
197
  {
143
- if (ctx) ctx->source_map.add_mapping(error);
144
- append_to_buffer("@error ");
198
+ append_indentation();
199
+ append_token("@error", error);
200
+ append_mandatory_space();
145
201
  error->message()->perform(this);
146
- append_to_buffer(";");
202
+ append_delimiter();
147
203
  }
148
204
 
149
205
  void Inspect::operator()(Debug* debug)
150
206
  {
151
- if (ctx) ctx->source_map.add_mapping(debug);
152
- append_to_buffer("@debug ");
207
+ append_indentation();
208
+ append_token("@debug", debug);
209
+ append_mandatory_space();
153
210
  debug->value()->perform(this);
154
- append_to_buffer(";");
211
+ append_delimiter();
155
212
  }
156
213
 
157
214
  void Inspect::operator()(Comment* comment)
158
215
  {
216
+ in_comment = true;
159
217
  comment->text()->perform(this);
218
+ in_comment = false;
160
219
  }
161
220
 
162
221
  void Inspect::operator()(If* cond)
163
222
  {
164
- append_to_buffer("@if ");
223
+ append_indentation();
224
+ append_token("@if", cond);
225
+ append_mandatory_space();
165
226
  cond->predicate()->perform(this);
166
227
  cond->consequent()->perform(this);
167
228
  if (cond->alternative()) {
168
- append_to_buffer("\n");
169
- indent();
170
- append_to_buffer("else");
229
+ append_optional_linefeed();
230
+ append_indentation();
231
+ append_string("else");
171
232
  cond->alternative()->perform(this);
172
233
  }
173
234
  }
174
235
 
175
236
  void Inspect::operator()(For* loop)
176
237
  {
177
- append_to_buffer("@for ");
178
- append_to_buffer(loop->variable());
179
- append_to_buffer(" from ");
238
+ append_indentation();
239
+ append_token("@for", loop);
240
+ append_mandatory_space();
241
+ append_string(loop->variable());
242
+ append_string(" from ");
180
243
  loop->lower_bound()->perform(this);
181
- append_to_buffer((loop->is_inclusive() ? " through " : " to "));
244
+ append_string(loop->is_inclusive() ? " through " : " to ");
182
245
  loop->upper_bound()->perform(this);
183
246
  loop->block()->perform(this);
184
247
  }
185
248
 
186
249
  void Inspect::operator()(Each* loop)
187
250
  {
188
- append_to_buffer("@each ");
189
- append_to_buffer(loop->variables()[0]);
251
+ append_indentation();
252
+ append_token("@each", loop);
253
+ append_mandatory_space();
254
+ append_string(loop->variables()[0]);
190
255
  for (size_t i = 1, L = loop->variables().size(); i < L; ++i) {
191
- append_to_buffer(", ");
192
- append_to_buffer(loop->variables()[i]);
256
+ append_comma_separator();
257
+ append_string(loop->variables()[i]);
193
258
  }
194
- append_to_buffer(" in ");
259
+ append_string(" in ");
195
260
  loop->list()->perform(this);
196
261
  loop->block()->perform(this);
197
262
  }
198
263
 
199
264
  void Inspect::operator()(While* loop)
200
265
  {
201
- append_to_buffer("@while ");
266
+ append_indentation();
267
+ append_token("@while", loop);
268
+ append_mandatory_space();
202
269
  loop->predicate()->perform(this);
203
270
  loop->block()->perform(this);
204
271
  }
205
272
 
206
273
  void Inspect::operator()(Return* ret)
207
274
  {
208
- append_to_buffer("@return ");
275
+ append_indentation();
276
+ append_token("@return", ret);
277
+ append_mandatory_space();
209
278
  ret->value()->perform(this);
210
- append_to_buffer(";");
279
+ append_delimiter();
211
280
  }
212
281
 
213
282
  void Inspect::operator()(Extension* extend)
214
283
  {
215
- append_to_buffer("@extend ");
284
+ append_indentation();
285
+ append_token("@extend", extend);
286
+ append_mandatory_space();
216
287
  extend->selector()->perform(this);
217
- append_to_buffer(";");
288
+ append_delimiter();
218
289
  }
219
290
 
220
291
  void Inspect::operator()(Definition* def)
221
292
  {
293
+ append_indentation();
222
294
  if (def->type() == Definition::MIXIN) {
223
- append_to_buffer("@mixin ");
295
+ append_token("@mixin", def);
296
+ append_mandatory_space();
224
297
  } else {
225
- append_to_buffer("@function ");
298
+ append_token("@function", def);
299
+ append_mandatory_space();
226
300
  }
227
- append_to_buffer(def->name());
301
+ append_string(def->name());
228
302
  def->parameters()->perform(this);
229
303
  def->block()->perform(this);
230
304
  }
231
305
 
232
306
  void Inspect::operator()(Mixin_Call* call)
233
307
  {
234
- append_to_buffer(string("@include ") += call->name());
308
+ append_indentation();
309
+ append_token("@include", call);
310
+ append_mandatory_space();
311
+ append_string(call->name());
235
312
  if (call->arguments()) {
236
313
  call->arguments()->perform(this);
237
314
  }
238
315
  if (call->block()) {
239
- append_to_buffer(" ");
316
+ append_optional_space();
240
317
  call->block()->perform(this);
241
318
  }
242
- if (!call->block()) append_to_buffer(";");
319
+ if (!call->block()) append_delimiter();
243
320
  }
244
321
 
245
322
  void Inspect::operator()(Content* content)
246
323
  {
247
- if (ctx) ctx->source_map.add_mapping(content);
248
- append_to_buffer("@content;");
324
+ append_indentation();
325
+ append_token("@content", content);
326
+ append_delimiter();
249
327
  }
250
328
 
251
329
  void Inspect::operator()(Map* map)
@@ -253,52 +331,60 @@ namespace Sass {
253
331
  if (map->empty()) return;
254
332
  if (map->is_invisible()) return;
255
333
  bool items_output = false;
256
- append_to_buffer("(");
334
+ append_string("(");
257
335
  for (auto key : map->keys()) {
258
336
  if (key->is_invisible()) continue;
259
337
  if (map->at(key)->is_invisible()) continue;
260
- if (items_output) append_to_buffer(", ");
338
+ if (items_output) append_comma_separator();
261
339
  key->perform(this);
262
- append_to_buffer(": ");
340
+ append_colon_separator();
263
341
  map->at(key)->perform(this);
264
342
  items_output = true;
265
343
  }
266
- append_to_buffer(")");
344
+ append_string(")");
267
345
  }
268
346
 
269
347
  void Inspect::operator()(List* list)
270
348
  {
271
- string sep(list->separator() == List::SPACE ? " " : ", ");
349
+ string sep(list->separator() == List::SPACE ? " " : ",");
350
+ if (output_style() != COMPRESSED && sep == ",") sep += " ";
351
+ else if (in_media_block && sep != " ") sep += " "; // verified
272
352
  if (list->empty()) return;
273
353
  bool items_output = false;
354
+ in_declaration_list = in_declaration;
274
355
  for (size_t i = 0, L = list->length(); i < L; ++i) {
275
356
  Expression* list_item = (*list)[i];
276
357
  if (list_item->is_invisible()) {
277
358
  continue;
278
359
  }
279
- if (items_output) append_to_buffer(sep);
360
+ if (items_output) {
361
+ append_string(sep);
362
+ }
363
+ if (items_output && sep != " ")
364
+ append_optional_space();
280
365
  list_item->perform(this);
281
366
  items_output = true;
282
367
  }
368
+ in_declaration_list = false;
283
369
  }
284
370
 
285
371
  void Inspect::operator()(Binary_Expression* expr)
286
372
  {
287
373
  expr->left()->perform(this);
288
374
  switch (expr->type()) {
289
- case Binary_Expression::AND: append_to_buffer(" and "); break;
290
- case Binary_Expression::OR: append_to_buffer(" or "); break;
291
- case Binary_Expression::EQ: append_to_buffer(" == "); break;
292
- case Binary_Expression::NEQ: append_to_buffer(" != "); break;
293
- case Binary_Expression::GT: append_to_buffer(" > "); break;
294
- case Binary_Expression::GTE: append_to_buffer(" >= "); break;
295
- case Binary_Expression::LT: append_to_buffer(" < "); break;
296
- case Binary_Expression::LTE: append_to_buffer(" <= "); break;
297
- case Binary_Expression::ADD: append_to_buffer(" + "); break;
298
- case Binary_Expression::SUB: append_to_buffer(" - "); break;
299
- case Binary_Expression::MUL: append_to_buffer(" * "); break;
300
- case Binary_Expression::DIV: append_to_buffer("/"); break;
301
- case Binary_Expression::MOD: append_to_buffer(" % "); break;
375
+ case Binary_Expression::AND: append_string(" and "); break;
376
+ case Binary_Expression::OR: append_string(" or "); break;
377
+ case Binary_Expression::EQ: append_string(" == "); break;
378
+ case Binary_Expression::NEQ: append_string(" != "); break;
379
+ case Binary_Expression::GT: append_string(" > "); break;
380
+ case Binary_Expression::GTE: append_string(" >= "); break;
381
+ case Binary_Expression::LT: append_string(" < "); break;
382
+ case Binary_Expression::LTE: append_string(" <= "); break;
383
+ case Binary_Expression::ADD: append_string(" + "); break;
384
+ case Binary_Expression::SUB: append_string(" - "); break;
385
+ case Binary_Expression::MUL: append_string(" * "); break;
386
+ case Binary_Expression::DIV: append_string("/"); break;
387
+ case Binary_Expression::MOD: append_string(" % "); break;
302
388
  default: break; // shouldn't get here
303
389
  }
304
390
  expr->right()->perform(this);
@@ -306,14 +392,14 @@ namespace Sass {
306
392
 
307
393
  void Inspect::operator()(Unary_Expression* expr)
308
394
  {
309
- if (expr->type() == Unary_Expression::PLUS) append_to_buffer("+");
310
- else append_to_buffer("-");
395
+ if (expr->type() == Unary_Expression::PLUS) append_string("+");
396
+ else append_string("-");
311
397
  expr->operand()->perform(this);
312
398
  }
313
399
 
314
400
  void Inspect::operator()(Function_Call* call)
315
401
  {
316
- append_to_buffer(call->name());
402
+ append_token(call->name(), call);
317
403
  call->arguments()->perform(this);
318
404
  }
319
405
 
@@ -325,34 +411,13 @@ namespace Sass {
325
411
 
326
412
  void Inspect::operator()(Variable* var)
327
413
  {
328
- append_to_buffer(var->name());
414
+ append_token(var->name(), var);
329
415
  }
330
416
 
331
417
  void Inspect::operator()(Textual* txt)
332
418
  {
333
- append_to_buffer(txt->value());
334
- }
335
-
336
- // helper functions for serializing numbers
337
- // string frac_to_string(double f, size_t p) {
338
- // stringstream ss;
339
- // ss.setf(ios::fixed, ios::floatfield);
340
- // ss.precision(p);
341
- // ss << f;
342
- // string result(ss.str().substr(f < 0 ? 2 : 1));
343
- // size_t i = result.size() - 1;
344
- // while (result[i] == '0') --i;
345
- // result = result.substr(0, i+1);
346
- // return result;
347
- // }
348
- // string double_to_string(double d, size_t p) {
349
- // stringstream ss;
350
- // double ipart;
351
- // double fpart = std::modf(d, &ipart);
352
- // ss << ipart;
353
- // if (fpart != 0) ss << frac_to_string(fpart, 5);
354
- // return ss.str();
355
- // }
419
+ append_token(txt->value(), txt);
420
+ }
356
421
 
357
422
  void Inspect::operator()(Number* n)
358
423
  {
@@ -368,10 +433,14 @@ namespace Sass {
368
433
  d.resize(d.length()-1);
369
434
  }
370
435
  if (d[d.length()-1] == '.') d.resize(d.length()-1);
371
- if (n->numerator_units().size() > 1 || n->denominator_units().size() > 0) {
372
- error(d + n->unit() + " is not a valid CSS value", n->path(), n->position());
373
- }
374
- if (!n->zero()) {
436
+ if (n->numerator_units().size() > 1 ||
437
+ n->denominator_units().size() > 0 ||
438
+ (n->numerator_units().size() && n->numerator_units()[0].find_first_of('/') != string::npos) ||
439
+ (n->numerator_units().size() && n->numerator_units()[0].find_first_of('*') != string::npos)
440
+ ) {
441
+ error(d + n->unit() + " isn't a valid CSS value.", n->pstate());
442
+ }
443
+ if (!n->zero() && !in_declaration_list) {
375
444
  if (d.substr(0, 3) == "-0.") d.erase(1, 1);
376
445
  if (d.substr(0, 2) == "0.") d.erase(0, 1);
377
446
  }
@@ -381,8 +450,7 @@ namespace Sass {
381
450
  // a value before it got truncated
382
451
  if (d == "0" && nonzero) d = "0.0";
383
452
  // append number and unit
384
- append_to_buffer(d);
385
- append_to_buffer(n->unit());
453
+ append_token(d + n->unit(), n);
386
454
  }
387
455
 
388
456
  // helper function for serializing colors
@@ -396,47 +464,85 @@ namespace Sass {
396
464
  void Inspect::operator()(Color* c)
397
465
  {
398
466
  stringstream ss;
467
+
468
+ // check if we prefer short hex colors
469
+ bool want_short = output_style() == COMPRESSED;
470
+
471
+ // original color name
472
+ // maybe an unknown token
473
+ string name = c->disp();
474
+
475
+ // resolved color
476
+ string res_name = name;
477
+
399
478
  double r = round(cap_channel<0xff>(c->r()));
400
479
  double g = round(cap_channel<0xff>(c->g()));
401
480
  double b = round(cap_channel<0xff>(c->b()));
402
481
  double a = cap_channel<1> (c->a());
403
482
 
483
+ // get color from given name (if one was given at all)
484
+ if (name != "" && ctx && ctx->names_to_colors.count(name)) {
485
+ Color* n = ctx->names_to_colors[name];
486
+ r = round(cap_channel<0xff>(n->r()));
487
+ g = round(cap_channel<0xff>(n->g()));
488
+ b = round(cap_channel<0xff>(n->b()));
489
+ a = cap_channel<1> (n->a());
490
+ }
491
+ // otherwise get the possible resolved color name
492
+ else {
493
+ int numval = static_cast<int>(r) * 0x10000 + static_cast<int>(g) * 0x100 + static_cast<int>(b);
494
+ if (ctx && ctx->colors_to_names.count(numval))
495
+ res_name = ctx->colors_to_names[numval];
496
+ }
497
+
498
+ stringstream hexlet;
499
+ hexlet << '#' << setw(1) << setfill('0');
500
+ // create a short color hexlet if there is any need for it
501
+ if (want_short && is_color_doublet(r, g, b) && a == 1) {
502
+ hexlet << hex << setw(1) << (static_cast<unsigned long>(r) >> 4);
503
+ hexlet << hex << setw(1) << (static_cast<unsigned long>(g) >> 4);
504
+ hexlet << hex << setw(1) << (static_cast<unsigned long>(b) >> 4);
505
+ } else {
506
+ hexlet << hex << setw(2) << static_cast<unsigned long>(r);
507
+ hexlet << hex << setw(2) << static_cast<unsigned long>(g);
508
+ hexlet << hex << setw(2) << static_cast<unsigned long>(b);
509
+ }
510
+
404
511
  // retain the originally specified color definition if unchanged
405
- if (!c->disp().empty()) {
406
- ss << c->disp();
512
+ if (name != "") {
513
+ ss << name;
407
514
  }
408
515
  else if (r == 0 && g == 0 && b == 0 && a == 0) {
409
516
  ss << "transparent";
410
517
  }
411
518
  else if (a >= 1) {
412
- // see if it's a named color
413
- int numval = r * 0x10000;
414
- numval += g * 0x100;
415
- numval += b;
416
- if (ctx && ctx->colors_to_names.count(numval)) {
417
- ss << ctx->colors_to_names[numval];
519
+ if (res_name != "") {
520
+ if (want_short && hexlet.str().size() < res_name.size()) {
521
+ ss << hexlet.str();
522
+ } else {
523
+ ss << res_name;
524
+ }
418
525
  }
419
526
  else {
420
- // otherwise output the hex triplet
421
- ss << '#' << setw(2) << setfill('0');
422
- ss << hex << setw(2) << static_cast<unsigned long>(r);
423
- ss << hex << setw(2) << static_cast<unsigned long>(g);
424
- ss << hex << setw(2) << static_cast<unsigned long>(b);
527
+ ss << hexlet.str();
425
528
  }
426
529
  }
427
530
  else {
428
531
  ss << "rgba(";
429
- ss << static_cast<unsigned long>(r) << ", ";
430
- ss << static_cast<unsigned long>(g) << ", ";
431
- ss << static_cast<unsigned long>(b) << ", ";
532
+ ss << static_cast<unsigned long>(r) << ",";
533
+ if (output_style() != COMPRESSED) ss << " ";
534
+ ss << static_cast<unsigned long>(g) << ",";
535
+ if (output_style() != COMPRESSED) ss << " ";
536
+ ss << static_cast<unsigned long>(b) << ",";
537
+ if (output_style() != COMPRESSED) ss << " ";
432
538
  ss << a << ')';
433
539
  }
434
- append_to_buffer(ss.str());
540
+ append_token(ss.str(), c);
435
541
  }
436
542
 
437
543
  void Inspect::operator()(Boolean* b)
438
544
  {
439
- append_to_buffer(b->value() ? "true" : "false");
545
+ append_token(b->value() ? "true" : "false", b);
440
546
  }
441
547
 
442
548
  void Inspect::operator()(String_Schema* ss)
@@ -444,15 +550,27 @@ namespace Sass {
444
550
  // Evaluation should turn these into String_Constants, so this method is
445
551
  // only for inspection purposes.
446
552
  for (size_t i = 0, L = ss->length(); i < L; ++i) {
447
- if ((*ss)[i]->is_interpolant()) append_to_buffer("#{");
553
+ if ((*ss)[i]->is_interpolant()) append_string("#{");
448
554
  (*ss)[i]->perform(this);
449
- if ((*ss)[i]->is_interpolant()) append_to_buffer("}");
555
+ if ((*ss)[i]->is_interpolant()) append_string("}");
450
556
  }
451
557
  }
452
558
 
453
559
  void Inspect::operator()(String_Constant* s)
454
560
  {
455
- append_to_buffer(s->needs_unquoting() ? unquote(s->value()) : s->value());
561
+ if (String_Quoted* quoted = dynamic_cast<String_Quoted*>(s)) {
562
+ return Inspect::operator()(quoted);
563
+ }
564
+ append_token(s->value(), s);
565
+ }
566
+
567
+ void Inspect::operator()(String_Quoted* s)
568
+ {
569
+ if (s->quote_mark()) {
570
+ append_token(quote(s->value(), s->quote_mark()), s);
571
+ } else {
572
+ append_token(s->value(), s);
573
+ }
456
574
  }
457
575
 
458
576
  void Inspect::operator()(Feature_Query* fq)
@@ -466,40 +584,46 @@ namespace Sass {
466
584
 
467
585
  void Inspect::operator()(Feature_Query_Condition* fqc)
468
586
  {
469
- if (fqc->operand() == Feature_Query_Condition::AND)
470
- append_to_buffer(" and ");
471
- else if (fqc->operand() == Feature_Query_Condition::OR)
472
- append_to_buffer(" or ");
473
- else if (fqc->operand() == Feature_Query_Condition::NOT)
474
- append_to_buffer(" not ");
587
+ if (fqc->operand() == Feature_Query_Condition::AND) {
588
+ append_mandatory_space();
589
+ append_token("and", fqc);
590
+ append_mandatory_space();
591
+ } else if (fqc->operand() == Feature_Query_Condition::OR) {
592
+ append_mandatory_space();
593
+ append_token("or", fqc);
594
+ append_mandatory_space();
595
+ } else if (fqc->operand() == Feature_Query_Condition::NOT) {
596
+ append_mandatory_space();
597
+ append_token("not", fqc);
598
+ append_mandatory_space();
599
+ }
475
600
 
476
- if (!fqc->is_root()) append_to_buffer("(");
601
+ if (!fqc->is_root()) append_string("(");
477
602
 
478
603
  if (!fqc->length()) {
479
604
  fqc->feature()->perform(this);
480
- append_to_buffer(": ");
605
+ append_string(": "); // verified
481
606
  fqc->value()->perform(this);
482
607
  }
483
- // else
484
608
  for (size_t i = 0, L = fqc->length(); i < L; ++i)
485
609
  (*fqc)[i]->perform(this);
486
610
 
487
- if (!fqc->is_root()) append_to_buffer(")");
611
+ if (!fqc->is_root()) append_string(")");
488
612
  }
489
613
 
490
614
  void Inspect::operator()(Media_Query* mq)
491
615
  {
492
616
  size_t i = 0;
493
617
  if (mq->media_type()) {
494
- if (mq->is_negated()) append_to_buffer("not ");
495
- else if (mq->is_restricted()) append_to_buffer("only ");
618
+ if (mq->is_negated()) append_string("not ");
619
+ else if (mq->is_restricted()) append_string("only ");
496
620
  mq->media_type()->perform(this);
497
621
  }
498
622
  else {
499
623
  (*mq)[i++]->perform(this);
500
624
  }
501
625
  for (size_t L = mq->length(); i < L; ++i) {
502
- append_to_buffer(" and ");
626
+ append_string(" and ");
503
627
  (*mq)[i]->perform(this);
504
628
  }
505
629
  }
@@ -510,77 +634,96 @@ namespace Sass {
510
634
  mqe->feature()->perform(this);
511
635
  }
512
636
  else {
513
- append_to_buffer("(");
637
+ append_string("(");
514
638
  mqe->feature()->perform(this);
515
639
  if (mqe->value()) {
516
- append_to_buffer(": ");
640
+ append_string(": "); // verified
517
641
  mqe->value()->perform(this);
518
642
  }
519
- append_to_buffer(")");
643
+ append_string(")");
644
+ }
645
+ }
646
+
647
+ void Inspect::operator()(At_Root_Expression* ae)
648
+ {
649
+ if (ae->is_interpolated()) {
650
+ ae->feature()->perform(this);
651
+ }
652
+ else {
653
+ append_string("(");
654
+ ae->feature()->perform(this);
655
+ if (ae->value()) {
656
+ append_colon_separator();
657
+ ae->value()->perform(this);
658
+ }
659
+ append_string(")");
520
660
  }
521
661
  }
522
662
 
523
663
  void Inspect::operator()(Null* n)
524
664
  {
525
- append_to_buffer("null");
665
+ append_token("null", n);
526
666
  }
527
667
 
528
668
  // parameters and arguments
529
669
  void Inspect::operator()(Parameter* p)
530
670
  {
531
- append_to_buffer(p->name());
671
+ append_token(p->name(), p);
532
672
  if (p->default_value()) {
533
- append_to_buffer(": ");
673
+ append_colon_separator();
534
674
  p->default_value()->perform(this);
535
675
  }
536
676
  else if (p->is_rest_parameter()) {
537
- append_to_buffer("...");
677
+ append_string("...");
538
678
  }
539
679
  }
540
680
 
541
681
  void Inspect::operator()(Parameters* p)
542
682
  {
543
- append_to_buffer("(");
683
+ append_string("(");
544
684
  if (!p->empty()) {
545
685
  (*p)[0]->perform(this);
546
686
  for (size_t i = 1, L = p->length(); i < L; ++i) {
547
- append_to_buffer(", ");
687
+ append_comma_separator();
548
688
  (*p)[i]->perform(this);
549
689
  }
550
690
  }
551
- append_to_buffer(")");
691
+ append_string(")");
552
692
  }
553
693
 
554
694
  void Inspect::operator()(Argument* a)
555
695
  {
556
696
  if (!a->name().empty()) {
557
- append_to_buffer(a->name());
558
- append_to_buffer(": ");
697
+ append_token(a->name(), a);
698
+ append_colon_separator();
559
699
  }
560
700
  // Special case: argument nulls can be ignored
561
701
  if (a->value()->concrete_type() == Expression::NULL_VAL) {
562
702
  return;
563
703
  }
564
- a->value()->perform(this);
704
+ if (a->value()->concrete_type() == Expression::STRING) {
705
+ String_Constant* s = static_cast<String_Constant*>(a->value());
706
+ s->perform(this);
707
+ } else a->value()->perform(this);
565
708
  if (a->is_rest_argument()) {
566
- append_to_buffer("...");
709
+ append_string("...");
567
710
  }
568
711
  }
569
712
 
570
713
  void Inspect::operator()(Arguments* a)
571
714
  {
572
- append_to_buffer("(");
715
+ append_string("(");
573
716
  if (!a->empty()) {
574
717
  (*a)[0]->perform(this);
575
718
  for (size_t i = 1, L = a->length(); i < L; ++i) {
576
- append_to_buffer(", ");
719
+ append_string(", "); // verified
720
+ // Sass Bug? append_comma_separator();
577
721
  (*a)[i]->perform(this);
578
722
  }
579
723
  }
580
- append_to_buffer(")");
724
+ append_string(")");
581
725
  }
582
726
 
583
- // selectors
584
727
  void Inspect::operator()(Selector_Schema* s)
585
728
  {
586
729
  s->contents()->perform(this);
@@ -589,57 +732,58 @@ namespace Sass {
589
732
  void Inspect::operator()(Selector_Reference* ref)
590
733
  {
591
734
  if (ref->selector()) ref->selector()->perform(this);
592
- else append_to_buffer("&");
735
+ else append_string("&");
593
736
  }
594
737
 
595
738
  void Inspect::operator()(Selector_Placeholder* s)
596
739
  {
597
- append_to_buffer(s->name());
740
+ append_token(s->name(), s);
741
+ if (s->has_line_break()) append_optional_linefeed();
742
+ if (s->has_line_break()) append_indentation();
743
+
598
744
  }
599
745
 
600
746
  void Inspect::operator()(Type_Selector* s)
601
747
  {
602
- if (ctx) ctx->source_map.add_mapping(s);
603
- append_to_buffer(s->name());
748
+ append_token(s->name(), s);
604
749
  }
605
750
 
606
751
  void Inspect::operator()(Selector_Qualifier* s)
607
752
  {
608
- if (ctx) ctx->source_map.add_mapping(s);
609
- append_to_buffer(s->name());
753
+ append_token(s->name(), s);
754
+ if (s->has_line_break()) append_optional_linefeed();
755
+ if (s->has_line_break()) append_indentation();
610
756
  }
611
757
 
612
758
  void Inspect::operator()(Attribute_Selector* s)
613
759
  {
614
- if (ctx) ctx->source_map.add_mapping(s);
615
- append_to_buffer("[");
616
- append_to_buffer(s->name());
760
+ append_string("[");
761
+ add_open_mapping(s);
762
+ append_token(s->name(), s);
617
763
  if (!s->matcher().empty()) {
618
- append_to_buffer(s->matcher());
764
+ append_string(s->matcher());
619
765
  if (s->value()) {
620
766
  s->value()->perform(this);
621
767
  }
622
- // append_to_buffer(s->value());
623
768
  }
624
- append_to_buffer("]");
769
+ add_close_mapping(s);
770
+ append_string("]");
625
771
  }
626
772
 
627
773
  void Inspect::operator()(Pseudo_Selector* s)
628
774
  {
629
- if (ctx) ctx->source_map.add_mapping(s);
630
- append_to_buffer(s->name());
775
+ append_token(s->name(), s);
631
776
  if (s->expression()) {
632
777
  s->expression()->perform(this);
633
- append_to_buffer(")");
778
+ append_string(")");
634
779
  }
635
780
  }
636
781
 
637
782
  void Inspect::operator()(Wrapped_Selector* s)
638
783
  {
639
- if (ctx) ctx->source_map.add_mapping(s);
640
- append_to_buffer(s->name());
784
+ append_token(s->name(), s);
641
785
  s->selector()->perform(this);
642
- append_to_buffer(")");
786
+ append_string(")");
643
787
  }
644
788
 
645
789
  void Inspect::operator()(Compound_Selector* s)
@@ -647,6 +791,9 @@ namespace Sass {
647
791
  for (size_t i = 0, L = s->length(); i < L; ++i) {
648
792
  (*s)[i]->perform(this);
649
793
  }
794
+ if (s->has_line_break()) {
795
+ append_optional_linefeed();
796
+ }
650
797
  }
651
798
 
652
799
  void Inspect::operator()(Complex_Selector* c)
@@ -655,15 +802,34 @@ namespace Sass {
655
802
  Complex_Selector* tail = c->tail();
656
803
  Complex_Selector::Combinator comb = c->combinator();
657
804
  if (head && !head->is_empty_reference()) head->perform(this);
658
- if (head && !head->is_empty_reference() && tail) append_to_buffer(" ");
805
+ bool is_empty = head && head->is_empty_reference();
806
+ bool is_tail = head && !head->is_empty_reference() && tail;
807
+ if (output_style() == COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0;
808
+
659
809
  switch (comb) {
660
- case Complex_Selector::ANCESTOR_OF: break;
661
- case Complex_Selector::PARENT_OF: append_to_buffer(">"); break;
662
- case Complex_Selector::PRECEDES: append_to_buffer("~"); break;
663
- case Complex_Selector::ADJACENT_TO: append_to_buffer("+"); break;
810
+ case Complex_Selector::ANCESTOR_OF:
811
+ if (is_tail) append_mandatory_space();
812
+ break;
813
+ case Complex_Selector::PARENT_OF:
814
+ append_optional_space();
815
+ append_string(">");
816
+ append_optional_space();
817
+ break;
818
+ case Complex_Selector::ADJACENT_TO:
819
+ append_optional_space();
820
+ append_string("+");
821
+ append_optional_space();
822
+ break;
823
+ case Complex_Selector::PRECEDES:
824
+ if (is_empty) append_optional_space();
825
+ else append_mandatory_space();
826
+ append_string("~");
827
+ if (tail) append_mandatory_space();
828
+ else append_optional_space();
829
+ break;
664
830
  }
665
831
  if (tail && comb != Complex_Selector::ANCESTOR_OF) {
666
- append_to_buffer(" ");
832
+ if (c->has_line_break()) append_optional_linefeed();
667
833
  }
668
834
  if (tail) tail->perform(this);
669
835
  }
@@ -671,57 +837,21 @@ namespace Sass {
671
837
  void Inspect::operator()(Selector_List* g)
672
838
  {
673
839
  if (g->empty()) return;
674
- (*g)[0]->perform(this);
675
- for (size_t i = 1, L = g->length(); i < L; ++i) {
676
- append_to_buffer(", ");
840
+ for (size_t i = 0, L = g->length(); i < L; ++i) {
841
+ if (!in_at_rule && i == 0) append_indentation();
677
842
  (*g)[i]->perform(this);
843
+ if (i < L - 1) {
844
+ append_comma_separator();
845
+ if ((*g)[i]->has_line_feed()) {
846
+ append_optional_linefeed();
847
+ append_indentation();
848
+ }
849
+ }
678
850
  }
679
851
  }
680
852
 
681
- inline void Inspect::fallback_impl(AST_Node* n)
682
- { }
683
-
684
- void Inspect::indent()
685
- { append_to_buffer(string(2*indentation, ' ')); }
686
-
687
- string unquote(const string& s)
688
- {
689
- if (s.empty()) return "";
690
- if (s.length() == 1) {
691
- if (s[0] == '"' || s[0] == '\'') return "";
692
- }
693
- char q;
694
- if (*s.begin() == '"' && *s.rbegin() == '"') q = '"';
695
- else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
696
- else return s;
697
- string t;
698
- t.reserve(s.length()-2);
699
- for (size_t i = 1, L = s.length()-1; i < L; ++i) {
700
- // if we see a quote, we need to remove the preceding backslash from t
701
- if (s[i-1] == '\\' && s[i] == q) t.erase(t.length()-1);
702
- t.push_back(s[i]);
703
- }
704
- return t;
705
- }
706
-
707
- string quote(const string& s, char q)
708
- {
709
- if (s.empty()) return string(2, q);
710
- if (!q || s[0] == '"' || s[0] == '\'') return s;
711
- string t;
712
- t.reserve(s.length()+2);
713
- t.push_back(q);
714
- for (size_t i = 0, L = s.length(); i < L; ++i) {
715
- if (s[i] == q) t.push_back('\\');
716
- t.push_back(s[i]);
717
- }
718
- t.push_back(q);
719
- return t;
720
- }
721
-
722
- void Inspect::append_to_buffer(const string& text)
853
+ void Inspect::fallback_impl(AST_Node* n)
723
854
  {
724
- buffer += text;
725
855
  }
726
856
 
727
857
  }