redsnow 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -1
  3. data/README.md +12 -0
  4. data/ext/snowcrash/bin/snowcrash +0 -0
  5. data/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.c +5 -2
  6. data/ext/snowcrash/snowcrash.gyp +7 -2
  7. data/ext/snowcrash/src/ActionParser.h +141 -81
  8. data/ext/snowcrash/src/AssetParser.h +19 -11
  9. data/ext/snowcrash/src/Blueprint.h +44 -14
  10. data/ext/snowcrash/src/BlueprintParser.h +65 -51
  11. data/ext/snowcrash/src/BlueprintSourcemap.h +254 -0
  12. data/ext/snowcrash/src/BlueprintUtility.h +3 -24
  13. data/ext/snowcrash/src/CBlueprint.cc +40 -31
  14. data/ext/snowcrash/src/CBlueprint.h +54 -58
  15. data/ext/snowcrash/src/CBlueprintSourcemap.cc +620 -0
  16. data/ext/snowcrash/src/CBlueprintSourcemap.h +342 -0
  17. data/ext/snowcrash/src/CSourceAnnotation.cc +14 -0
  18. data/ext/snowcrash/src/CodeBlockUtility.h +42 -5
  19. data/ext/snowcrash/src/HeadersParser.h +84 -42
  20. data/ext/snowcrash/src/ParameterParser.h +110 -68
  21. data/ext/snowcrash/src/ParametersParser.h +26 -28
  22. data/ext/snowcrash/src/PayloadParser.h +164 -83
  23. data/ext/snowcrash/src/ResourceGroupParser.h +35 -41
  24. data/ext/snowcrash/src/ResourceParser.h +142 -97
  25. data/ext/snowcrash/src/SectionParser.h +15 -14
  26. data/ext/snowcrash/src/SectionParserData.h +11 -2
  27. data/ext/snowcrash/src/SectionProcessor.h +42 -18
  28. data/ext/snowcrash/src/Serialize.cc +2 -0
  29. data/ext/snowcrash/src/Serialize.h +3 -1
  30. data/ext/snowcrash/src/SerializeJSON.cc +608 -16
  31. data/ext/snowcrash/src/SerializeJSON.h +4 -1
  32. data/ext/snowcrash/src/SerializeYAML.cc +367 -19
  33. data/ext/snowcrash/src/SerializeYAML.h +4 -1
  34. data/ext/snowcrash/src/SymbolTable.h +12 -1
  35. data/ext/snowcrash/src/ValuesParser.h +12 -11
  36. data/ext/snowcrash/src/Version.h +1 -1
  37. data/ext/snowcrash/src/csnowcrash.cc +7 -3
  38. data/ext/snowcrash/src/csnowcrash.h +4 -2
  39. data/ext/snowcrash/src/snowcrash.cc +10 -11
  40. data/ext/snowcrash/src/snowcrash.h +3 -3
  41. data/ext/snowcrash/src/snowcrash/snowcrash.cc +38 -8
  42. data/ext/snowcrash/tools/homebrew/snowcrash.rb +1 -1
  43. data/lib/redsnow.rb +41 -2
  44. data/lib/redsnow/binding.rb +93 -8
  45. data/lib/redsnow/blueprint.rb +48 -25
  46. data/lib/redsnow/parseresult.rb +9 -2
  47. data/lib/redsnow/sourcemap.rb +369 -0
  48. data/lib/redsnow/version.rb +1 -1
  49. data/test/fixtures/sample-api-ast.json +1 -1
  50. data/test/fixtures/sample-api-sourcemap.json +169 -0
  51. data/test/redsnow_binding_test.rb +19 -2
  52. data/test/redsnow_options_test.rb +42 -0
  53. data/test/redsnow_parseresult_test.rb +5 -1
  54. data/test/redsnow_test.rb +5 -0
  55. metadata +11 -2
@@ -17,14 +17,12 @@ namespace snowcrash {
17
17
 
18
18
  const char* const GroupHeaderRegex = "^[[:blank:]]*[Gg]roup[[:blank:]]+" SYMBOL_IDENTIFIER "[[:blank:]]*$";
19
19
 
20
- /** Resource iterator pair: its containment group and resource iterator itself */
21
- typedef std::pair<Collection<ResourceGroup>::const_iterator, ResourceIterator> ResourceIteratorPair;
22
-
23
- /** Internal type alias for Collection of Resource */
24
- typedef Collection<ResourceGroup>::type ResourceGroups;
25
-
20
+ /** Internal type alias for Collection iterator of Resource */
26
21
  typedef Collection<ResourceGroup>::const_iterator ResourceGroupIterator;
27
22
 
23
+ /** Resource iterator pair: its containment group and resource iterator itself */
24
+ typedef std::pair<ResourceGroupIterator, ResourceIterator> ResourceIteratorPair;
25
+
28
26
  /**
29
27
  * ResourceGroup Section processor
30
28
  */
@@ -35,8 +33,7 @@ namespace snowcrash {
35
33
  const MarkdownNodes& siblings,
36
34
  SectionParserData& pd,
37
35
  SectionLayout& layout,
38
- Report& report,
39
- ResourceGroup& out) {
36
+ ParseResult<ResourceGroup>& out) {
40
37
 
41
38
  MarkdownNodeIterator cur = node;
42
39
  SectionType nestedType = nestedSectionType(cur);
@@ -50,8 +47,12 @@ namespace snowcrash {
50
47
  CaptureGroups captureGroups;
51
48
 
52
49
  if (RegexCapture(node->text, GroupHeaderRegex, captureGroups, 3)) {
53
- out.name = captureGroups[1];
54
- TrimString(out.name);
50
+ out.node.name = captureGroups[1];
51
+ TrimString(out.node.name);
52
+ }
53
+
54
+ if (pd.exportSourceMap() && !out.node.name.empty()) {
55
+ out.sourceMap.name.sourceMap = node->sourceMap;
55
56
  }
56
57
 
57
58
  return ++MarkdownNodeIterator(node);
@@ -60,32 +61,35 @@ namespace snowcrash {
60
61
  static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
61
62
  const MarkdownNodes& siblings,
62
63
  SectionParserData& pd,
63
- Report& report,
64
- ResourceGroup& out) {
64
+ ParseResult<ResourceGroup>& out) {
65
65
 
66
66
  if (pd.sectionContext() == ResourceSectionType) {
67
67
 
68
- Resource resource;
69
- MarkdownNodeIterator cur = ResourceParser::parse(node, siblings, pd, report, resource);
68
+ ParseResult<Resource> resource(out.report);
69
+ MarkdownNodeIterator cur = ResourceParser::parse(node, siblings, pd, resource);
70
70
 
71
- ResourceIterator duplicate = findResource(out.resources, resource);
71
+ ResourceIterator duplicate = SectionProcessor<Resource>::findResource(out.node.resources, resource.node);
72
72
  ResourceIteratorPair globalDuplicate;
73
73
 
74
- if (duplicate == out.resources.end()) {
75
- globalDuplicate = findResource(pd.blueprint, resource);
74
+ if (duplicate == out.node.resources.end()) {
75
+ globalDuplicate = findResource(pd.blueprint, resource.node);
76
76
  }
77
77
 
78
- if (duplicate != out.resources.end() ||
78
+ if (duplicate != out.node.resources.end() ||
79
79
  globalDuplicate.first != pd.blueprint.resourceGroups.end()) {
80
80
 
81
81
  // WARN: Duplicate resource
82
82
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
83
- report.warnings.push_back(Warning("the resource '" + resource.uriTemplate + "' is already defined",
84
- DuplicateWarning,
85
- sourceMap));
83
+ out.report.warnings.push_back(Warning("the resource '" + resource.node.uriTemplate + "' is already defined",
84
+ DuplicateWarning,
85
+ sourceMap));
86
86
  }
87
87
 
88
- out.resources.push_back(resource);
88
+ out.node.resources.push_back(resource.node);
89
+
90
+ if (pd.exportSourceMap()) {
91
+ out.sourceMap.resources.collection.push_back(resource.sourceMap);
92
+ }
89
93
 
90
94
  return cur;
91
95
  }
@@ -97,11 +101,10 @@ namespace snowcrash {
97
101
  const MarkdownNodes& siblings,
98
102
  SectionParserData& pd,
99
103
  SectionType& lastSectionType,
100
- Report& report,
101
- ResourceGroup& out) {
104
+ ParseResult<ResourceGroup>& out) {
102
105
 
103
106
  if (SectionProcessor<Action>::actionType(node) == DependentActionType &&
104
- !out.resources.empty()) {
107
+ !out.node.resources.empty()) {
105
108
 
106
109
  mdp::ByteBuffer method;
107
110
  mdp::ByteBuffer name;
@@ -111,17 +114,17 @@ namespace snowcrash {
111
114
 
112
115
  // WARN: Unexpected action
113
116
  std::stringstream ss;
114
- ss << "unexpected action '" << method << "', to define multiple actions for the '" << out.resources.back().uriTemplate;
117
+ ss << "unexpected action '" << method << "', to define multiple actions for the '" << out.node.resources.back().uriTemplate;
115
118
  ss << "' resource omit the HTTP method in its definition, e.g. '# /resource'";
116
119
 
117
- report.warnings.push_back(Warning(ss.str(),
118
- IgnoringWarning,
119
- sourceMap));
120
+ out.report.warnings.push_back(Warning(ss.str(),
121
+ IgnoringWarning,
122
+ sourceMap));
120
123
 
121
124
  return ++MarkdownNodeIterator(node);
122
125
  }
123
126
 
124
- return SectionProcessorBase<ResourceGroup>::processUnexpectedNode(node, siblings, pd, lastSectionType, report, out);
127
+ return SectionProcessorBase<ResourceGroup>::processUnexpectedNode(node, siblings, pd, lastSectionType, out);
125
128
  }
126
129
 
127
130
  static SectionType sectionType(const MarkdownNodeIterator& node) {
@@ -179,24 +182,15 @@ namespace snowcrash {
179
182
  return SectionProcessorBase<ResourceGroup>::isUnexpectedNode(node, sectionType);
180
183
  }
181
184
 
182
- /** Finds a resource inside an resources collection */
183
- static ResourceIterator findResource(const Resources& resources,
184
- const Resource& resource) {
185
-
186
- return std::find_if(resources.begin(),
187
- resources.end(),
188
- std::bind2nd(MatchResource(), resource));
189
- }
190
-
191
185
  /** Finds a resource in blueprint by its URI template */
192
186
  static ResourceIteratorPair findResource(const Blueprint& blueprint,
193
187
  const Resource& resource) {
194
188
 
195
- for (Collection<ResourceGroup>::const_iterator it = blueprint.resourceGroups.begin();
189
+ for (ResourceGroupIterator it = blueprint.resourceGroups.begin();
196
190
  it != blueprint.resourceGroups.end();
197
191
  ++it) {
198
192
 
199
- ResourceIterator match = findResource(it->resources, resource);
193
+ ResourceIterator match = SectionProcessor<Resource>::findResource(it->resources, resource);
200
194
 
201
195
  if (match != it->resources.end()) {
202
196
  return std::make_pair(it, match);
@@ -24,9 +24,7 @@ namespace snowcrash {
24
24
  /** Named resource matching regex */
25
25
  const char* const NamedResourceHeaderRegex = "^[[:blank:]]*" SYMBOL_IDENTIFIER "[[:blank:]]+\\[" URI_TEMPLATE "]$";
26
26
 
27
- /** Internal type alias for Collection of Resource */
28
- typedef Collection<Resource>::type Resources;
29
-
27
+ /** Internal type alias for Collection iterator of Resource */
30
28
  typedef Collection<Resource>::const_iterator ResourceIterator;
31
29
 
32
30
  /**
@@ -39,32 +37,46 @@ namespace snowcrash {
39
37
  const MarkdownNodes& siblings,
40
38
  SectionParserData& pd,
41
39
  SectionLayout& layout,
42
- Report& report,
43
- Resource& out) {
40
+ ParseResult<Resource>& out) {
44
41
 
45
42
  CaptureGroups captureGroups;
46
43
 
47
44
  // If Abbreviated resource section
48
45
  if (RegexCapture(node->text, ResourceHeaderRegex, captureGroups, 4)) {
49
46
 
50
- out.uriTemplate = captureGroups[3];
47
+ out.node.uriTemplate = captureGroups[3];
51
48
 
52
49
  // Make this section an action
53
50
  if (!captureGroups[2].empty()) {
54
51
 
55
- Action action;
56
- MarkdownNodeIterator cur = ActionParser::parse(node, node->parent().children(), pd, report, action);
52
+ ParseResult<Action> action(out.report);
53
+ MarkdownNodeIterator cur = ActionParser::parse(node, node->parent().children(), pd, action);
57
54
 
58
- out.actions.push_back(action);
55
+ out.node.actions.push_back(action.node);
59
56
  layout = RedirectSectionLayout;
60
57
 
58
+ if (pd.exportSourceMap()) {
59
+ out.sourceMap.actions.collection.push_back(action.sourceMap);
60
+ out.sourceMap.uriTemplate.sourceMap = node->sourceMap;
61
+ }
62
+
61
63
  return cur;
62
64
  }
63
65
  } else if (RegexCapture(node->text, NamedResourceHeaderRegex, captureGroups, 4)) {
64
66
 
65
- out.name = captureGroups[1];
66
- TrimString(out.name);
67
- out.uriTemplate = captureGroups[2];
67
+ out.node.name = captureGroups[1];
68
+ TrimString(out.node.name);
69
+ out.node.uriTemplate = captureGroups[2];
70
+ }
71
+
72
+ if (pd.exportSourceMap()) {
73
+ if (!out.node.uriTemplate.empty()) {
74
+ out.sourceMap.uriTemplate.sourceMap = node->sourceMap;
75
+ }
76
+
77
+ if (!out.node.name.empty()) {
78
+ out.sourceMap.name.sourceMap = node->sourceMap;
79
+ }
68
80
  }
69
81
 
70
82
  return ++MarkdownNodeIterator(node);
@@ -73,22 +85,24 @@ namespace snowcrash {
73
85
  static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
74
86
  const MarkdownNodes& siblings,
75
87
  SectionParserData& pd,
76
- Report& report,
77
- Resource& out) {
88
+ ParseResult<Resource>& out) {
78
89
 
79
90
  switch (pd.sectionContext()) {
80
91
  case ActionSectionType:
81
- return processAction(node, siblings, pd, report, out);
92
+ return processAction(node, siblings, pd, out);
82
93
 
83
94
  case ParametersSectionType:
84
- return processParameters(node, siblings, pd, report, out);
95
+ return processParameters(node, siblings, pd, out);
85
96
 
86
97
  case ModelSectionType:
87
98
  case ModelBodySectionType:
88
- return processModel(node, siblings, pd, report, out);
99
+ return processModel(node, siblings, pd, out);
89
100
 
90
101
  case HeadersSectionType:
91
- return SectionProcessor<Action>::handleDeprecatedHeaders(node, siblings, pd, report, out.headers);
102
+ {
103
+ ParseResult<Headers> headers(out.report, out.node.headers, out.sourceMap.headers);
104
+ return SectionProcessor<Action>::handleDeprecatedHeaders(node, siblings, pd, headers);
105
+ }
92
106
 
93
107
  default:
94
108
  break;
@@ -101,27 +115,34 @@ namespace snowcrash {
101
115
  const MarkdownNodes& siblings,
102
116
  SectionParserData& pd,
103
117
  SectionType& sectionType,
104
- Report& report,
105
- Resource& out) {
118
+ ParseResult<Resource>& out) {
106
119
 
107
120
  if ((node->type == mdp::ParagraphMarkdownNodeType ||
108
121
  node->type == mdp::CodeMarkdownNodeType) &&
109
122
  (sectionType == ModelBodySectionType ||
110
123
  sectionType == ModelSectionType)) {
111
124
 
112
- CodeBlockUtility::addDanglingAsset(node, pd, sectionType, report, out.model.body);
125
+ mdp::ByteBuffer content = CodeBlockUtility::addDanglingAsset(node, pd, sectionType, out.report, out.node.model.body);
126
+
127
+ if (pd.exportSourceMap() && !content.empty()) {
128
+ out.sourceMap.model.body.sourceMap.append(node->sourceMap);
129
+ }
113
130
 
114
131
  // Update model in the symbol table as well
115
- ResourceModelSymbolTable::iterator it = pd.symbolTable.resourceModels.find(out.model.name);
132
+ ResourceModelSymbolTable::iterator it = pd.symbolTable.resourceModels.find(out.node.model.name);
116
133
 
117
134
  if (it != pd.symbolTable.resourceModels.end()) {
118
- it->second.body = out.model.body;
135
+ it->second.body = out.node.model.body;
136
+
137
+ if (pd.exportSourceMap()) {
138
+ pd.symbolSourceMapTable.resourceModels[out.node.model.name].body = out.sourceMap.model.body;
139
+ }
119
140
  }
120
141
 
121
142
  return ++MarkdownNodeIterator(node);
122
143
  }
123
144
 
124
- return SectionProcessorBase<Resource>::processUnexpectedNode(node, siblings, pd, sectionType, report, out);
145
+ return SectionProcessorBase<Resource>::processUnexpectedNode(node, siblings, pd, sectionType, out);
125
146
  }
126
147
 
127
148
  static bool isDescriptionNode(const MarkdownNodeIterator& node,
@@ -212,33 +233,39 @@ namespace snowcrash {
212
233
 
213
234
  static void finalize(const MarkdownNodeIterator& node,
214
235
  SectionParserData& pd,
215
- Report& report,
216
- Resource& out) {
236
+ ParseResult<Resource>& out) {
217
237
 
218
- if (!out.uriTemplate.empty()) {
238
+ if (!out.node.uriTemplate.empty()) {
219
239
 
220
240
  URITemplateParser uriTemplateParser;
221
241
  ParsedURITemplate parsedResult;
222
242
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
223
243
 
224
- uriTemplateParser.parse(out.uriTemplate, sourceMap, parsedResult);
244
+ uriTemplateParser.parse(out.node.uriTemplate, sourceMap, parsedResult);
225
245
 
226
246
  if (!parsedResult.report.warnings.empty()) {
227
- report += parsedResult.report;
247
+ out.report += parsedResult.report;
228
248
  }
229
249
  }
230
250
 
231
- // Consolidate depraceted headers into subsequent payloads
232
- if (!out.headers.empty()) {
251
+ // Consolidate deprecated headers into subsequent payloads
252
+ if (!out.node.headers.empty()) {
233
253
 
234
- for (Collection<Action>::iterator it = out.actions.begin();
235
- it != out.actions.end();
236
- ++it) {
254
+ Collection<Action>::iterator actIt = out.node.actions.begin();
255
+ Collection<SourceMap<Action> >::iterator actSMIt = out.sourceMap.actions.collection.begin();
237
256
 
238
- SectionProcessor<Headers>::injectDeprecatedHeaders(out.headers, it->examples);
257
+ for (;
258
+ actIt != out.node.actions.end();
259
+ ++actIt, ++actSMIt) {
260
+
261
+ SectionProcessor<Headers>::injectDeprecatedHeaders(pd, out.node.headers, out.sourceMap.headers, actIt->examples, actSMIt->examples);
239
262
  }
240
263
 
241
- out.headers.clear();
264
+ out.node.headers.clear();
265
+
266
+ if (pd.exportSourceMap()) {
267
+ out.sourceMap.headers.collection.clear();
268
+ }
242
269
  }
243
270
  }
244
271
 
@@ -246,33 +273,36 @@ namespace snowcrash {
246
273
  static MarkdownNodeIterator processAction(const MarkdownNodeIterator& node,
247
274
  const MarkdownNodes& siblings,
248
275
  SectionParserData& pd,
249
- Report& report,
250
- Resource& out) {
276
+ ParseResult<Resource>& out) {
251
277
 
252
- Action action;
253
- MarkdownNodeIterator cur = ActionParser::parse(node, siblings, pd, report, action);
278
+ ParseResult<Action> action(out.report);
279
+ MarkdownNodeIterator cur = ActionParser::parse(node, siblings, pd, action);
254
280
 
255
- ActionIterator duplicate = findAction(out.actions, action);
281
+ ActionIterator duplicate = SectionProcessor<Action>::findAction(out.node.actions, action.node);
256
282
 
257
- if (duplicate != out.actions.end()) {
283
+ if (duplicate != out.node.actions.end()) {
258
284
 
259
285
  // WARN: duplicate method
260
286
  std::stringstream ss;
261
- ss << "action with method '" << action.method << "' already defined for resource '";
262
- ss << out.uriTemplate << "'";
287
+ ss << "action with method '" << action.node.method << "' already defined for resource '";
288
+ ss << out.node.uriTemplate << "'";
263
289
 
264
290
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
265
- report.warnings.push_back(Warning(ss.str(),
266
- DuplicateWarning,
267
- sourceMap));
291
+ out.report.warnings.push_back(Warning(ss.str(),
292
+ DuplicateWarning,
293
+ sourceMap));
268
294
  }
269
295
 
270
- if (!action.parameters.empty()) {
296
+ if (!action.node.parameters.empty()) {
271
297
 
272
- checkParametersEligibility(node, pd, out, action.parameters, report);
298
+ checkParametersEligibility(node, pd, action.node.parameters, out);
273
299
  }
274
300
 
275
- out.actions.push_back(action);
301
+ out.node.actions.push_back(action.node);
302
+
303
+ if (pd.exportSourceMap()) {
304
+ out.sourceMap.actions.collection.push_back(action.sourceMap);
305
+ }
276
306
 
277
307
  return cur;
278
308
  }
@@ -281,16 +311,21 @@ namespace snowcrash {
281
311
  static MarkdownNodeIterator processParameters(const MarkdownNodeIterator& node,
282
312
  const MarkdownNodes& siblings,
283
313
  SectionParserData& pd,
284
- Report& report,
285
- Resource& out) {
314
+ ParseResult<Resource>& out) {
286
315
 
287
- Parameters parameters;
288
- MarkdownNodeIterator cur = ParametersParser::parse(node, siblings, pd, report, parameters);
316
+ ParseResult<Parameters> parameters(out.report);
317
+ MarkdownNodeIterator cur = ParametersParser::parse(node, siblings, pd, parameters);
289
318
 
290
- if (!parameters.empty()) {
319
+ if (!parameters.node.empty()) {
291
320
 
292
- checkParametersEligibility(node, pd, out, parameters, report);
293
- out.parameters.insert(out.parameters.end(), parameters.begin(), parameters.end());
321
+ checkParametersEligibility(node, pd, parameters.node, out);
322
+ out.node.parameters.insert(out.node.parameters.end(), parameters.node.begin(), parameters.node.end());
323
+
324
+ if (pd.exportSourceMap()) {
325
+ out.sourceMap.parameters.collection.insert(out.sourceMap.parameters.collection.end(),
326
+ parameters.sourceMap.collection.begin(),
327
+ parameters.sourceMap.collection.end());
328
+ }
294
329
  }
295
330
 
296
331
  return cur;
@@ -300,69 +335,80 @@ namespace snowcrash {
300
335
  static MarkdownNodeIterator processModel(const MarkdownNodeIterator& node,
301
336
  const MarkdownNodes& siblings,
302
337
  SectionParserData& pd,
303
- Report& report,
304
- Resource& out) {
338
+ ParseResult<Resource>& out) {
305
339
 
306
- Payload model;
307
- MarkdownNodeIterator cur = PayloadParser::parse(node, siblings, pd, report, model);
340
+ ParseResult<Payload> model(out.report);
341
+ MarkdownNodeIterator cur = PayloadParser::parse(node, siblings, pd, model);
308
342
 
309
343
  // Check whether there isn't a model already
310
- if (!out.model.name.empty()) {
344
+ if (!out.node.model.name.empty()) {
311
345
 
312
346
  // WARN: Model already defined
313
347
  std::stringstream ss;
314
348
  ss << "overshadowing previous model definition for '";
315
349
 
316
- if (!out.name.empty()) {
317
- ss << out.name << "(" << out.uriTemplate << ")";
350
+ if (!out.node.name.empty()) {
351
+ ss << out.node.name << "(" << out.node.uriTemplate << ")";
318
352
  } else {
319
- ss << out.uriTemplate;
353
+ ss << out.node.uriTemplate;
320
354
  }
321
355
 
322
356
  ss << "' resource, a resource can be represented by a single model only";
323
357
 
324
358
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
325
- report.warnings.push_back(Warning(ss.str(),
326
- DuplicateWarning,
327
- sourceMap));
359
+ out.report.warnings.push_back(Warning(ss.str(),
360
+ DuplicateWarning,
361
+ sourceMap));
328
362
  }
329
363
 
330
- if (model.name.empty()) {
364
+ if (model.node.name.empty()) {
365
+
366
+ if (!out.node.name.empty()) {
367
+ model.node.name = out.node.name;
331
368
 
332
- if (!out.name.empty()) {
333
- model.name = out.name;
369
+ if (pd.exportSourceMap()) {
370
+ model.sourceMap.name = out.sourceMap.name;
371
+ }
334
372
  } else {
335
373
 
336
374
  // ERR: No name specified for resource model
337
375
  std::stringstream ss;
338
376
  ss << "resource model can be specified only for a named resource";
339
- ss << ", name your resource, e.g. '# <resource name> [" << out.uriTemplate << "]'";
377
+ ss << ", name your resource, e.g. '# <resource name> [" << out.node.uriTemplate << "]'";
340
378
 
341
379
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
342
- report.error = Error(ss.str(),
343
- SymbolError,
344
- sourceMap);
380
+ out.report.error = Error(ss.str(),
381
+ SymbolError,
382
+ sourceMap);
345
383
  }
346
384
  }
347
385
 
348
- ResourceModelSymbolTable::iterator it = pd.symbolTable.resourceModels.find(model.name);
386
+ ResourceModelSymbolTable::iterator it = pd.symbolTable.resourceModels.find(model.node.name);
349
387
 
350
388
  if (it == pd.symbolTable.resourceModels.end()) {
351
389
 
352
- pd.symbolTable.resourceModels[model.name] = model;
390
+ pd.symbolTable.resourceModels[model.node.name] = model.node;
391
+
392
+ if (pd.exportSourceMap()) {
393
+ pd.symbolSourceMapTable.resourceModels[model.node.name] = model.sourceMap;
394
+ }
353
395
  } else {
354
396
 
355
397
  // ERR: Symbol already defined
356
398
  std::stringstream ss;
357
- ss << "symbol '" << model.name << "' already defined";
399
+ ss << "symbol '" << model.node.name << "' already defined";
358
400
 
359
401
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
360
- report.error = Error(ss.str(),
361
- SymbolError,
362
- sourceMap);
402
+ out.report.error = Error(ss.str(),
403
+ SymbolError,
404
+ sourceMap);
363
405
  }
364
406
 
365
- out.model = model;
407
+ out.node.model = model.node;
408
+
409
+ if (pd.exportSourceMap()) {
410
+ out.sourceMap.model = model.sourceMap;
411
+ }
366
412
 
367
413
  return cur;
368
414
  }
@@ -370,42 +416,41 @@ namespace snowcrash {
370
416
  /** Check Parameters eligibility in URI template */
371
417
  static void checkParametersEligibility(const MarkdownNodeIterator& node,
372
418
  const SectionParserData& pd,
373
- Resource& resource,
374
419
  Parameters& parameters,
375
- Report& report) {
420
+ ParseResult<Resource>& out) {
376
421
 
377
422
  for (ParameterIterator it = parameters.begin();
378
423
  it != parameters.end();
379
424
  ++it) {
380
425
 
381
426
  // Naive check whether parameter is present in URI Template
382
- if (resource.uriTemplate.find(it->name) == std::string::npos) {
427
+ if (out.node.uriTemplate.find(it->name) == std::string::npos) {
383
428
 
384
429
  // WARN: parameter name not present
385
430
  std::stringstream ss;
386
431
  ss << "parameter '" << it->name << "' not specified in ";
387
432
 
388
- if (!resource.name.empty()) {
389
- ss << "'" << resource.name << "' ";
433
+ if (!out.node.name.empty()) {
434
+ ss << "'" << out.node.name << "' ";
390
435
  }
391
436
 
392
- ss << "its '" << resource.uriTemplate << "' URI template";
437
+ ss << "its '" << out.node.uriTemplate << "' URI template";
393
438
 
394
439
  mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
395
- report.warnings.push_back(Warning(ss.str(),
396
- LogicalErrorWarning,
397
- sourceMap));
440
+ out.report.warnings.push_back(Warning(ss.str(),
441
+ LogicalErrorWarning,
442
+ sourceMap));
398
443
  }
399
444
  }
400
445
  }
401
446
 
402
- /** Finds an action inside an actions collection */
403
- static ActionIterator findAction(const Actions& actions,
404
- const Action& action) {
447
+ /** Finds a resource inside an resources collection */
448
+ static ResourceIterator findResource(const Resources& resources,
449
+ const Resource& resource) {
405
450
 
406
- return std::find_if(actions.begin(),
407
- actions.end(),
408
- std::bind2nd(MatchAction<Action>(), action));
451
+ return std::find_if(resources.begin(),
452
+ resources.end(),
453
+ std::bind2nd(MatchResource(), resource));
409
454
  }
410
455
  };
411
456