redsnow 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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