redsnow 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -1
- data/README.md +12 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.c +5 -2
- data/ext/snowcrash/snowcrash.gyp +7 -2
- data/ext/snowcrash/src/ActionParser.h +141 -81
- data/ext/snowcrash/src/AssetParser.h +19 -11
- data/ext/snowcrash/src/Blueprint.h +44 -14
- data/ext/snowcrash/src/BlueprintParser.h +65 -51
- data/ext/snowcrash/src/BlueprintSourcemap.h +254 -0
- data/ext/snowcrash/src/BlueprintUtility.h +3 -24
- data/ext/snowcrash/src/CBlueprint.cc +40 -31
- data/ext/snowcrash/src/CBlueprint.h +54 -58
- data/ext/snowcrash/src/CBlueprintSourcemap.cc +620 -0
- data/ext/snowcrash/src/CBlueprintSourcemap.h +342 -0
- data/ext/snowcrash/src/CSourceAnnotation.cc +14 -0
- data/ext/snowcrash/src/CodeBlockUtility.h +42 -5
- data/ext/snowcrash/src/HeadersParser.h +84 -42
- data/ext/snowcrash/src/ParameterParser.h +110 -68
- data/ext/snowcrash/src/ParametersParser.h +26 -28
- data/ext/snowcrash/src/PayloadParser.h +164 -83
- data/ext/snowcrash/src/ResourceGroupParser.h +35 -41
- data/ext/snowcrash/src/ResourceParser.h +142 -97
- data/ext/snowcrash/src/SectionParser.h +15 -14
- data/ext/snowcrash/src/SectionParserData.h +11 -2
- data/ext/snowcrash/src/SectionProcessor.h +42 -18
- data/ext/snowcrash/src/Serialize.cc +2 -0
- data/ext/snowcrash/src/Serialize.h +3 -1
- data/ext/snowcrash/src/SerializeJSON.cc +608 -16
- data/ext/snowcrash/src/SerializeJSON.h +4 -1
- data/ext/snowcrash/src/SerializeYAML.cc +367 -19
- data/ext/snowcrash/src/SerializeYAML.h +4 -1
- data/ext/snowcrash/src/SymbolTable.h +12 -1
- data/ext/snowcrash/src/ValuesParser.h +12 -11
- data/ext/snowcrash/src/Version.h +1 -1
- data/ext/snowcrash/src/csnowcrash.cc +7 -3
- data/ext/snowcrash/src/csnowcrash.h +4 -2
- data/ext/snowcrash/src/snowcrash.cc +10 -11
- data/ext/snowcrash/src/snowcrash.h +3 -3
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +38 -8
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +1 -1
- data/lib/redsnow.rb +41 -2
- data/lib/redsnow/binding.rb +93 -8
- data/lib/redsnow/blueprint.rb +48 -25
- data/lib/redsnow/parseresult.rb +9 -2
- data/lib/redsnow/sourcemap.rb +369 -0
- data/lib/redsnow/version.rb +1 -1
- data/test/fixtures/sample-api-ast.json +1 -1
- data/test/fixtures/sample-api-sourcemap.json +169 -0
- data/test/redsnow_binding_test.rb +19 -2
- data/test/redsnow_options_test.rb +42 -0
- data/test/redsnow_parseresult_test.rb +5 -1
- data/test/redsnow_test.rb +5 -0
- 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
|
-
/**
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
85
|
-
|
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
|
-
|
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
|
-
|
119
|
-
|
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,
|
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 (
|
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
|
-
|
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,
|
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
|
-
|
77
|
-
Resource& out) {
|
88
|
+
ParseResult<Resource>& out) {
|
78
89
|
|
79
90
|
switch (pd.sectionContext()) {
|
80
91
|
case ActionSectionType:
|
81
|
-
return processAction(node, siblings, pd,
|
92
|
+
return processAction(node, siblings, pd, out);
|
82
93
|
|
83
94
|
case ParametersSectionType:
|
84
|
-
return processParameters(node, siblings, pd,
|
95
|
+
return processParameters(node, siblings, pd, out);
|
85
96
|
|
86
97
|
case ModelSectionType:
|
87
98
|
case ModelBodySectionType:
|
88
|
-
return processModel(node, siblings, pd,
|
99
|
+
return processModel(node, siblings, pd, out);
|
89
100
|
|
90
101
|
case HeadersSectionType:
|
91
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
232
|
-
if (!out.headers.empty()) {
|
251
|
+
// Consolidate deprecated headers into subsequent payloads
|
252
|
+
if (!out.node.headers.empty()) {
|
233
253
|
|
234
|
-
|
235
|
-
|
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
|
-
|
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
|
-
|
250
|
-
Resource& out) {
|
276
|
+
ParseResult<Resource>& out) {
|
251
277
|
|
252
|
-
Action action;
|
253
|
-
MarkdownNodeIterator cur = ActionParser::parse(node, siblings, pd,
|
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
|
-
|
267
|
-
|
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,
|
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
|
-
|
285
|
-
Resource& out) {
|
314
|
+
ParseResult<Resource>& out) {
|
286
315
|
|
287
|
-
Parameters parameters;
|
288
|
-
MarkdownNodeIterator cur = ParametersParser::parse(node, siblings, pd,
|
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,
|
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
|
-
|
304
|
-
Resource& out) {
|
338
|
+
ParseResult<Resource>& out) {
|
305
339
|
|
306
|
-
Payload model;
|
307
|
-
MarkdownNodeIterator cur = PayloadParser::parse(node, siblings, pd,
|
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
|
-
|
327
|
-
|
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
|
-
|
333
|
-
|
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
|
-
|
344
|
-
|
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
|
-
|
362
|
-
|
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
|
-
|
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 (
|
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 (!
|
389
|
-
ss << "'" <<
|
433
|
+
if (!out.node.name.empty()) {
|
434
|
+
ss << "'" << out.node.name << "' ";
|
390
435
|
}
|
391
436
|
|
392
|
-
ss << "its '" <<
|
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
|
-
|
397
|
-
|
440
|
+
out.report.warnings.push_back(Warning(ss.str(),
|
441
|
+
LogicalErrorWarning,
|
442
|
+
sourceMap));
|
398
443
|
}
|
399
444
|
}
|
400
445
|
}
|
401
446
|
|
402
|
-
/** Finds
|
403
|
-
static
|
404
|
-
|
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(
|
407
|
-
|
408
|
-
std::bind2nd(
|
451
|
+
return std::find_if(resources.begin(),
|
452
|
+
resources.end(),
|
453
|
+
std::bind2nd(MatchResource(), resource));
|
409
454
|
}
|
410
455
|
};
|
411
456
|
|