redsnow 0.0.8

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 (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +20 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +62 -0
  9. data/Rakefile +36 -0
  10. data/Vagrantfile +20 -0
  11. data/ext/snowcrash/Makefile +64 -0
  12. data/ext/snowcrash/Vagrantfile +20 -0
  13. data/ext/snowcrash/bin/snowcrash +0 -0
  14. data/ext/snowcrash/common.gypi +163 -0
  15. data/ext/snowcrash/config.gypi +10 -0
  16. data/ext/snowcrash/config.mk +5 -0
  17. data/ext/snowcrash/configure +213 -0
  18. data/ext/snowcrash/provisioning.sh +15 -0
  19. data/ext/snowcrash/snowcrash.gyp +141 -0
  20. data/ext/snowcrash/src/ActionParser.h +503 -0
  21. data/ext/snowcrash/src/AssetParser.h +215 -0
  22. data/ext/snowcrash/src/BlockUtility.h +186 -0
  23. data/ext/snowcrash/src/Blueprint.h +283 -0
  24. data/ext/snowcrash/src/BlueprintParser.h +347 -0
  25. data/ext/snowcrash/src/BlueprintParserCore.h +190 -0
  26. data/ext/snowcrash/src/BlueprintSection.h +140 -0
  27. data/ext/snowcrash/src/BlueprintUtility.h +126 -0
  28. data/ext/snowcrash/src/CBlueprint.cc +600 -0
  29. data/ext/snowcrash/src/CBlueprint.h +354 -0
  30. data/ext/snowcrash/src/CSourceAnnotation.cc +140 -0
  31. data/ext/snowcrash/src/CSourceAnnotation.h +106 -0
  32. data/ext/snowcrash/src/CodeBlockUtility.h +189 -0
  33. data/ext/snowcrash/src/DescriptionSectionUtility.h +156 -0
  34. data/ext/snowcrash/src/HTTP.cc +46 -0
  35. data/ext/snowcrash/src/HTTP.h +105 -0
  36. data/ext/snowcrash/src/HeaderParser.h +289 -0
  37. data/ext/snowcrash/src/ListBlockUtility.h +273 -0
  38. data/ext/snowcrash/src/ListUtility.h +95 -0
  39. data/ext/snowcrash/src/MarkdownBlock.cc +176 -0
  40. data/ext/snowcrash/src/MarkdownBlock.h +93 -0
  41. data/ext/snowcrash/src/MarkdownParser.cc +266 -0
  42. data/ext/snowcrash/src/MarkdownParser.h +88 -0
  43. data/ext/snowcrash/src/ParameterDefinitonParser.h +570 -0
  44. data/ext/snowcrash/src/ParametersParser.h +252 -0
  45. data/ext/snowcrash/src/Parser.cc +71 -0
  46. data/ext/snowcrash/src/Parser.h +29 -0
  47. data/ext/snowcrash/src/ParserCore.cc +120 -0
  48. data/ext/snowcrash/src/ParserCore.h +82 -0
  49. data/ext/snowcrash/src/PayloadParser.h +672 -0
  50. data/ext/snowcrash/src/Platform.h +54 -0
  51. data/ext/snowcrash/src/RegexMatch.h +32 -0
  52. data/ext/snowcrash/src/ResourceGroupParser.h +195 -0
  53. data/ext/snowcrash/src/ResourceParser.h +584 -0
  54. data/ext/snowcrash/src/SectionUtility.h +142 -0
  55. data/ext/snowcrash/src/Serialize.cc +52 -0
  56. data/ext/snowcrash/src/Serialize.h +69 -0
  57. data/ext/snowcrash/src/SerializeJSON.cc +601 -0
  58. data/ext/snowcrash/src/SerializeJSON.h +21 -0
  59. data/ext/snowcrash/src/SerializeYAML.cc +336 -0
  60. data/ext/snowcrash/src/SerializeYAML.h +21 -0
  61. data/ext/snowcrash/src/SourceAnnotation.h +177 -0
  62. data/ext/snowcrash/src/StringUtility.h +109 -0
  63. data/ext/snowcrash/src/SymbolTable.h +83 -0
  64. data/ext/snowcrash/src/UriTemplateParser.cc +195 -0
  65. data/ext/snowcrash/src/UriTemplateParser.h +243 -0
  66. data/ext/snowcrash/src/Version.h +39 -0
  67. data/ext/snowcrash/src/csnowcrash.cc +23 -0
  68. data/ext/snowcrash/src/csnowcrash.h +38 -0
  69. data/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
  70. data/ext/snowcrash/src/snowcrash.cc +18 -0
  71. data/ext/snowcrash/src/snowcrash.h +41 -0
  72. data/ext/snowcrash/src/snowcrash/snowcrash.cc +170 -0
  73. data/ext/snowcrash/src/win/RegexMatch.cc +78 -0
  74. data/ext/snowcrash/sundown/CONTRIBUTING.md +10 -0
  75. data/ext/snowcrash/sundown/Makefile +83 -0
  76. data/ext/snowcrash/sundown/Makefile.win +33 -0
  77. data/ext/snowcrash/sundown/examples/smartypants.c +72 -0
  78. data/ext/snowcrash/sundown/examples/sundown.c +80 -0
  79. data/ext/snowcrash/sundown/html/houdini.h +37 -0
  80. data/ext/snowcrash/sundown/html/houdini_href_e.c +108 -0
  81. data/ext/snowcrash/sundown/html/houdini_html_e.c +84 -0
  82. data/ext/snowcrash/sundown/html/html.c +647 -0
  83. data/ext/snowcrash/sundown/html/html.h +77 -0
  84. data/ext/snowcrash/sundown/html/html_smartypants.c +389 -0
  85. data/ext/snowcrash/sundown/html_block_names.txt +25 -0
  86. data/ext/snowcrash/sundown/src/autolink.c +297 -0
  87. data/ext/snowcrash/sundown/src/autolink.h +51 -0
  88. data/ext/snowcrash/sundown/src/buffer.c +225 -0
  89. data/ext/snowcrash/sundown/src/buffer.h +96 -0
  90. data/ext/snowcrash/sundown/src/html_blocks.h +206 -0
  91. data/ext/snowcrash/sundown/src/markdown.c +2701 -0
  92. data/ext/snowcrash/sundown/src/markdown.h +147 -0
  93. data/ext/snowcrash/sundown/src/src_map.c +200 -0
  94. data/ext/snowcrash/sundown/src/src_map.h +58 -0
  95. data/ext/snowcrash/sundown/src/stack.c +81 -0
  96. data/ext/snowcrash/sundown/src/stack.h +29 -0
  97. data/ext/snowcrash/sundown/sundown.def +20 -0
  98. data/ext/snowcrash/tools/gyp/AUTHORS +11 -0
  99. data/ext/snowcrash/tools/gyp/DEPS +24 -0
  100. data/ext/snowcrash/tools/gyp/OWNERS +1 -0
  101. data/ext/snowcrash/tools/gyp/PRESUBMIT.py +120 -0
  102. data/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +190 -0
  103. data/ext/snowcrash/tools/gyp/codereview.settings +10 -0
  104. data/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
  105. data/ext/snowcrash/tools/gyp/gyp +8 -0
  106. data/ext/snowcrash/tools/gyp/gyp.bat +5 -0
  107. data/ext/snowcrash/tools/gyp/gyp_main.py +18 -0
  108. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
  109. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
  110. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1063 -0
  111. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
  112. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
  113. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +267 -0
  114. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +409 -0
  115. data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +537 -0
  116. data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
  117. data/ext/snowcrash/tools/gyp/pylib/gyp/common.py +521 -0
  118. data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
  119. data/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
  120. data/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +49 -0
  121. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
  122. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
  123. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
  124. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1143 -0
  125. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +81 -0
  126. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +335 -0
  127. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +87 -0
  128. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
  129. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2181 -0
  130. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
  131. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3335 -0
  132. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2156 -0
  133. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1224 -0
  134. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
  135. data/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2809 -0
  136. data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
  137. data/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +510 -0
  138. data/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +972 -0
  139. data/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
  140. data/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
  141. data/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +292 -0
  142. data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1440 -0
  143. data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
  144. data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2889 -0
  145. data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
  146. data/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
  147. data/ext/snowcrash/tools/gyp/pylintrc +307 -0
  148. data/ext/snowcrash/tools/gyp/samples/samples +81 -0
  149. data/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
  150. data/ext/snowcrash/tools/gyp/setup.py +19 -0
  151. data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
  152. data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
  153. data/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +252 -0
  154. data/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
  155. data/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
  156. data/ext/snowcrash/tools/gyp/tools/pretty_sln.py +168 -0
  157. data/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
  158. data/ext/snowcrash/tools/homebrew/snowcrash.rb +11 -0
  159. data/ext/snowcrash/vcbuild.bat +184 -0
  160. data/lib/redsnow.rb +31 -0
  161. data/lib/redsnow/binding.rb +132 -0
  162. data/lib/redsnow/blueprint.rb +365 -0
  163. data/lib/redsnow/object.rb +18 -0
  164. data/lib/redsnow/parseresult.rb +107 -0
  165. data/lib/redsnow/version.rb +4 -0
  166. data/provisioning.sh +20 -0
  167. data/redsnow.gemspec +35 -0
  168. data/test/_helper.rb +15 -0
  169. data/test/fixtures/sample-api-ast.json +97 -0
  170. data/test/fixtures/sample-api.apib +20 -0
  171. data/test/redsnow_binding_test.rb +35 -0
  172. data/test/redsnow_parseresult_test.rb +50 -0
  173. data/test/redsnow_test.rb +285 -0
  174. metadata +358 -0
@@ -0,0 +1,347 @@
1
+ //
2
+ // BlueprintParser.h
3
+ // snowcrash
4
+ //
5
+ // Created by Zdenek Nemec on 4/16/13.
6
+ // Copyright (c) 2013 Apiary Inc. All rights reserved.
7
+ //
8
+
9
+ #ifndef SNOWCRASH_BLUEPRINTPARSER_H
10
+ #define SNOWCRASH_BLUEPRINTPARSER_H
11
+
12
+ #include <functional>
13
+ #include <sstream>
14
+ #include <iterator>
15
+ #include "Blueprint.h"
16
+ #include "BlueprintParserCore.h"
17
+ #include "ResourceParser.h"
18
+ #include "ResourceGroupParser.h"
19
+
20
+ namespace snowcrashconst {
21
+
22
+ const char* const ExpectedAPINameMessage = "expected API name, e.g. '# <API Name>'";
23
+ }
24
+
25
+ namespace snowcrash {
26
+
27
+ /** Internal list items classifier, Blueprint Context */
28
+ template <>
29
+ FORCEINLINE SectionType ClassifyInternaListBlock<Blueprint>(const BlockIterator& begin,
30
+ const BlockIterator& end) {
31
+ return UndefinedSectionType;
32
+ }
33
+
34
+ /** Block Classifier, Blueprint Context */
35
+ template <>
36
+ FORCEINLINE SectionType ClassifyBlock<Blueprint>(const BlockIterator& begin,
37
+ const BlockIterator& end,
38
+ const SectionType& context) {
39
+
40
+ if (HasResourceGroupSignature(*begin) ||
41
+ HasResourceSignature(*begin))
42
+ return ResourceGroupSectionType; // Treat Resource as anonymous resource group
43
+
44
+ return (context == ResourceGroupSectionType) ? UndefinedSectionType : BlueprintSectionType;
45
+ }
46
+
47
+
48
+ /** Blueprint SectionType Parser */
49
+ template<>
50
+ struct SectionParser<Blueprint> {
51
+
52
+ static ParseSectionResult ParseSection(const BlueprintSection& section,
53
+ const BlockIterator& cur,
54
+ BlueprintParserCore& parser,
55
+ Blueprint& output) {
56
+
57
+ ParseSectionResult result = std::make_pair(Result(), cur);
58
+
59
+ switch (section.type) {
60
+
61
+ case BlueprintSectionType:
62
+ result = HandleBlueprintDescriptionBlock(section, cur, parser, output);
63
+ break;
64
+
65
+ case ResourceGroupSectionType:
66
+ result = HandleResourceGroup(section, cur, parser, output);
67
+ break;
68
+
69
+ default:
70
+ result.first.error = UnexpectedBlockError(section, cur, parser.sourceData);
71
+ break;
72
+ }
73
+
74
+ return result;
75
+ }
76
+
77
+ static void Finalize(const SectionBounds& bounds,
78
+ BlueprintParserCore& parser,
79
+ Blueprint& blueprint,
80
+ Result& result) {}
81
+
82
+ /**
83
+ * \brief Checks API Blueprint name issues warning or error if name does not exists.
84
+ * \param cur Cursor to the expected name header block
85
+ * \param blueprint Blueprint to check.
86
+ * \param parser A parser's instance.
87
+ * \param result Check result report.
88
+ * \result Returns false if a name is missing AND RequireBlueprintNameOption is set. True otherwise.
89
+ */
90
+ static bool CheckBlueprintName(const BlockIterator& cur,
91
+ const Blueprint& blueprint,
92
+ BlueprintParserCore& parser,
93
+ Result& result) {
94
+
95
+ if (!blueprint.name.empty())
96
+ return true;
97
+
98
+ if (parser.options & RequireBlueprintNameOption) {
99
+
100
+ // ERR: No API name specified
101
+ result.error = Error(snowcrashconst::ExpectedAPINameMessage,
102
+ BusinessError,
103
+ MapSourceDataBlock(cur->sourceMap, parser.sourceData));
104
+ return false;
105
+ }
106
+
107
+ // WARN: No API name specified
108
+ result.warnings.push_back(Warning(snowcrashconst::ExpectedAPINameMessage,
109
+ APINameWarning,
110
+ MapSourceDataBlock(cur->sourceMap, parser.sourceData)));
111
+
112
+ return true;
113
+ }
114
+
115
+ // Returns true if given block is first block in document
116
+ // after metadata block, false otherwise.
117
+ static bool IsFirstBlock(const BlockIterator& cur,
118
+ const SectionBounds& bounds,
119
+ const Blueprint& blueprint) {
120
+
121
+ if (blueprint.metadata.empty())
122
+ return cur == bounds.first;
123
+
124
+ return std::distance(bounds.first, cur) == 1;
125
+ }
126
+
127
+ static ParseSectionResult HandleBlueprintDescriptionBlock(const BlueprintSection& section,
128
+ const BlockIterator& cur,
129
+ BlueprintParserCore& parser,
130
+ Blueprint& output) {
131
+
132
+ ParseSectionResult result = std::make_pair(Result(), cur);
133
+ BlockIterator sectionCur(cur);
134
+
135
+ // API Name
136
+ bool isFirstBlock = IsFirstBlock(cur, section.bounds, output);
137
+ if (isFirstBlock &&
138
+ sectionCur->type == HeaderBlockType) {
139
+
140
+ output.name = cur->content;
141
+
142
+ // Check ambiguity
143
+ CheckHeaderBlock<Blueprint>(section, sectionCur, parser.sourceData, result.first);
144
+
145
+ // Check Name
146
+ if (!CheckBlueprintName(sectionCur, output, parser, result.first))
147
+ return result;
148
+
149
+ result.second = ++sectionCur;
150
+ return result;
151
+ }
152
+
153
+ // Metadata
154
+ if (isFirstBlock &&
155
+ sectionCur->type == ParagraphBlockType) {
156
+
157
+ result = ParseMetadataBlock(sectionCur, section.bounds, parser, output);
158
+ if (result.second != sectionCur)
159
+ return result;
160
+ }
161
+
162
+ // Description
163
+ result = ParseDescriptionBlock<Blueprint>(section, sectionCur, parser.sourceData, output);
164
+
165
+ // Check Name
166
+ if (isFirstBlock)
167
+ CheckBlueprintName(sectionCur, output, parser, result.first);
168
+
169
+ return result;
170
+ }
171
+
172
+ static ParseSectionResult HandleResourceGroup(const BlueprintSection& section,
173
+ const BlockIterator& cur,
174
+ BlueprintParserCore& parser,
175
+ Blueprint& output)
176
+ {
177
+
178
+ // Mandatory name check
179
+ ParseSectionResult result = std::make_pair(Result(), cur);
180
+ if (IsFirstBlock(cur, section.bounds, output) &&
181
+ !CheckBlueprintName(cur, output, parser, result.first))
182
+ return result;
183
+
184
+ // Parser resource group
185
+ ResourceGroup resourceGroup;
186
+ result = ResourceGroupParser::Parse(cur,
187
+ section.bounds.second,
188
+ section,
189
+ parser,
190
+ resourceGroup);
191
+
192
+ if (result.first.error.code != Error::OK)
193
+ return result;
194
+
195
+ Collection<ResourceGroup>::const_iterator duplicate = FindResourceGroup(parser.blueprint, resourceGroup);
196
+ if (duplicate != parser.blueprint.resourceGroups.end()) {
197
+
198
+ // WARN: duplicate group
199
+ std::stringstream ss;
200
+ if (resourceGroup.name.empty()) {
201
+ ss << "anonymous group";
202
+ }
203
+ else {
204
+ ss << "group '" << resourceGroup.name << "'";
205
+ }
206
+ ss << " is already defined";
207
+
208
+ SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur, section.bounds.second, section.bounds, parser.sourceData);
209
+ result.first.warnings.push_back(Warning(ss.str(),
210
+ DuplicateWarning,
211
+ sourceBlock));
212
+ }
213
+
214
+ output.resourceGroups.push_back(resourceGroup); // FIXME: C++11 move
215
+ return result;
216
+ }
217
+
218
+
219
+ static ParseSectionResult ParseMetadataBlock(const BlockIterator& cur,
220
+ const SectionBounds& bounds,
221
+ BlueprintParserCore& parser,
222
+ Blueprint& output) {
223
+
224
+ typedef Collection<Metadata>::type MetadataCollection;
225
+ typedef Collection<Metadata>::iterator MetadataCollectionIterator;
226
+ MetadataCollection metadataCollection;
227
+
228
+ ParseSectionResult result = std::make_pair(Result(), cur);
229
+ SourceData content = cur->content;
230
+ TrimStringEnd(content);
231
+ std::vector<std::string> lines = Split(content, '\n');
232
+ for (std::vector<std::string>::iterator line = lines.begin();
233
+ line != lines.end();
234
+ ++line) {
235
+
236
+ Metadata metadata;
237
+ if (KeyValueFromLine(*line, metadata))
238
+ metadataCollection.push_back(metadata);
239
+ }
240
+
241
+ if (lines.size() == metadataCollection.size()) {
242
+
243
+ // Check duplicates
244
+ std::vector<std::string> duplicateKeys;
245
+ for (MetadataCollectionIterator it = metadataCollection.begin();
246
+ it != metadataCollection.end();
247
+ ++it) {
248
+
249
+ MetadataCollectionIterator from = it;
250
+ if (++from == metadataCollection.end())
251
+ break;
252
+
253
+ MetadataCollectionIterator duplicate = std::find_if(from,
254
+ metadataCollection.end(),
255
+ std::bind2nd(MatchFirsts<Metadata>(), *it));
256
+
257
+ if (duplicate != metadataCollection.end() &&
258
+ std::find(duplicateKeys.begin(), duplicateKeys.end(), it->first) == duplicateKeys.end()) {
259
+
260
+ duplicateKeys.push_back(it->first);
261
+
262
+ // WARN: duplicate metada definition
263
+ std::stringstream ss;
264
+ ss << "duplicate definition of '" << it->first << "'";
265
+
266
+ SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur, bounds.second, bounds, parser.sourceData);
267
+ result.first.warnings.push_back(Warning(ss.str(),
268
+ DuplicateWarning,
269
+ sourceBlock));
270
+ }
271
+ }
272
+
273
+ // Insert parsed metadata into output
274
+ output.metadata.insert(output.metadata.end(),
275
+ metadataCollection.begin(),
276
+ metadataCollection.end());
277
+
278
+ ++result.second;
279
+ }
280
+ else if (!metadataCollection.empty()) {
281
+ // WARN: malformed metadata block
282
+ SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur, bounds.second, bounds, parser.sourceData);
283
+ result.first.warnings.push_back(Warning("ignoring possible metadata, expected"
284
+ " '<key> : <value>', one one per line",
285
+ FormattingWarning,
286
+ sourceBlock));
287
+ }
288
+
289
+ return result;
290
+ }
291
+ };
292
+
293
+ typedef BlockParser<Blueprint, SectionParser<Blueprint> > BlueprintParserInner;
294
+
295
+
296
+ //
297
+ // Blueprint Parser
298
+ //
299
+ class BlueprintParser {
300
+ public:
301
+ // Parse Markdown AST into API Blueprint AST
302
+ static void Parse(const SourceData& sourceData,
303
+ const MarkdownBlock::Stack& source,
304
+ BlueprintParserOptions options,
305
+ Result& result,
306
+ Blueprint& blueprint) {
307
+
308
+ BlueprintParserCore parser(options, sourceData, blueprint);
309
+ BlueprintSection rootSection(std::make_pair(source.begin(), source.end()));
310
+ ParseSectionResult sectionResult = BlueprintParserInner::Parse(source.begin(),
311
+ source.end(),
312
+ rootSection,
313
+ parser,
314
+ blueprint);
315
+ result += sectionResult.first;
316
+
317
+ #ifdef DEBUG
318
+ PrintSymbolTable(parser.symbolTable);
319
+ #endif
320
+ if (result.error.code != Error::OK)
321
+ return;
322
+
323
+ PostParseCheck(sourceData, source, parser, result);
324
+ }
325
+
326
+ /**
327
+ * Perform additional post-parsing result checks.
328
+ * Mainly to focused on running checking when top-level parser is not executed.
329
+ */
330
+ static void PostParseCheck(const SourceData& sourceData,
331
+ const MarkdownBlock::Stack& source,
332
+ BlueprintParserCore& parser,
333
+ Result& result) {
334
+
335
+ if ((parser.options & RequireBlueprintNameOption) &&
336
+ parser.blueprint.name.empty()){
337
+
338
+ // ERR: No API name specified
339
+ result.error = Error(snowcrashconst::ExpectedAPINameMessage,
340
+ BusinessError,
341
+ MapSourceDataBlock(MakeSourceDataBlock(0, 0), parser.sourceData));
342
+ }
343
+ }
344
+ };
345
+ }
346
+
347
+ #endif
@@ -0,0 +1,190 @@
1
+ //
2
+ // BlueprintParserCore.h
3
+ // snowcrash
4
+ //
5
+ // Created by Zdenek Nemec on 5/4/13.
6
+ // Copyright (c) 2013 Apiary Inc. All rights reserved.
7
+ //
8
+
9
+ #ifndef SNOWCRASH_BLUEPRINTPARSERCORE_H
10
+ #define SNOWCRASH_BLUEPRINTPARSERCORE_H
11
+
12
+ #include <algorithm>
13
+ #include <sstream>
14
+ #include "ParserCore.h"
15
+ #include "SourceAnnotation.h"
16
+ #include "MarkdownBlock.h"
17
+ #include "BlueprintSection.h"
18
+ #include "HTTP.h"
19
+ #include "Blueprint.h"
20
+ #include "BlueprintUtility.h"
21
+ #include "StringUtility.h"
22
+ #include "SymbolTable.h"
23
+
24
+ namespace snowcrash {
25
+
26
+ /**
27
+ * \brief Blueprint Parser Options.
28
+ *
29
+ * Controls blueprint parser behavior.
30
+ */
31
+ enum BlueprintParserOption {
32
+ RenderDescriptionsOption = (1 << 0), /// < Render Markdown in description.
33
+ RequireBlueprintNameOption = (1 << 1) /// < Treat missing blueprint name as error
34
+ };
35
+
36
+ typedef unsigned int BlueprintParserOptions;
37
+
38
+ /**
39
+ * \brief Parsing subroutine result
40
+ *
41
+ * Consists of a parsing result report (first) and
42
+ * %BlockIterator (second) pointing to the last parsed
43
+ * markdown block.
44
+ */
45
+ typedef std::pair<Result, BlockIterator> ParseSectionResult;
46
+
47
+
48
+ /**
49
+ * Parser Core Data
50
+ */
51
+ struct BlueprintParserCore {
52
+ BlueprintParserCore(BlueprintParserOptions opts,
53
+ const SourceData& src,
54
+ const Blueprint& bp)
55
+ : options(opts), sourceData(src), blueprint(bp) {}
56
+
57
+ /** Parser Options */
58
+ BlueprintParserOptions options;
59
+
60
+ /** Symbol Table */
61
+ SymbolTable symbolTable;
62
+
63
+ /** Source Data */
64
+ const SourceData& sourceData;
65
+
66
+ /** AST being parsed **/
67
+ const Blueprint& blueprint;
68
+
69
+ private:
70
+ BlueprintParserCore();
71
+ BlueprintParserCore(const BlueprintParserCore&);
72
+ BlueprintParserCore& operator=(const BlueprintParserCore&);
73
+ };
74
+
75
+ /**
76
+ * SectionType Parser prototype.
77
+ */
78
+ template<class T>
79
+ struct SectionParser {
80
+
81
+ /**
82
+ * \brief Parse section's blocks.
83
+ * \param section Actual section being parsed.
84
+ * \param cur Cursor within the section boundaries.
85
+ * \param parser Parser instance.
86
+ * \param output AST node parsed.
87
+ * \return %ParseSectionResult pointing to the last block parsed & including
88
+ * any possible source annotations in the form of results or warnings.
89
+ */
90
+ static ParseSectionResult ParseSection(const BlueprintSection& section,
91
+ const BlockIterator& cur,
92
+ BlueprintParserCore& parser,
93
+ T& output);
94
+
95
+ /**
96
+ * \brief Optional post-parse processing.
97
+ */
98
+ static void Finalize(const SectionBounds& bounds,
99
+ BlueprintParserCore& parser,
100
+ T& output,
101
+ Result& result);
102
+ };
103
+
104
+ /**
105
+ * \brief Internal list items classifier prototype.
106
+ *
107
+ * The classifier might look ahead.
108
+ * DO NOT provide generic implementation.
109
+ */
110
+ template <class T>
111
+ FORCEINLINE SectionType ClassifyInternaListBlock(const BlockIterator& begin,
112
+ const BlockIterator& end);
113
+ /**
114
+ * \brief Classify a block with children list items.
115
+ *
116
+ * Classifies internal list block & descend to children list block classifiers.
117
+ * DO NOT provide generic implementation.
118
+ */
119
+ template <class T>
120
+ FORCEINLINE SectionType ClassifyChildrenListBlock(const BlockIterator& begin,
121
+ const BlockIterator& end);
122
+
123
+ /**
124
+ * \brief Block Classifier prototype.
125
+ *
126
+ * The classifier might look ahead.
127
+ */
128
+ template <class T>
129
+ FORCEINLINE SectionType ClassifyBlock(const BlockIterator& begin,
130
+ const BlockIterator& end,
131
+ const SectionType& context);
132
+
133
+ // Forward declaration of classifier helpers
134
+ extern bool HasResourceGroupSignature(const MarkdownBlock& block);
135
+ extern bool HasActionSignature(const MarkdownBlock& block);
136
+ extern bool HasResourceSignature(const MarkdownBlock& block);
137
+ extern bool HasPayloadSignature(const BlockIterator& begin, const BlockIterator& end);
138
+ extern bool HasPayloadAssetSignature(const BlockIterator& begin, const BlockIterator& end);
139
+ extern bool HasAssetSignature(const BlockIterator& begin, const BlockIterator& end);
140
+ extern bool HasHeaderSignature(const BlockIterator& begin, const BlockIterator& end);
141
+ extern bool HasParametersSignature(const BlockIterator& begin, const BlockIterator& end);
142
+
143
+ /**
144
+ * \brief A Markdown block parser.
145
+ *
146
+ * Iterates over blocks classifying sections and calling relevant %SectionParser P<T>.
147
+ */
148
+ template <class T, class P>
149
+ struct BlockParser : public P {
150
+
151
+ // Iterate blocks, classify & parse
152
+ static ParseSectionResult Parse(const BlockIterator& begin,
153
+ const BlockIterator& end,
154
+ const BlueprintSection& parentSection,
155
+ BlueprintParserCore& parser,
156
+ T& output) {
157
+ Result result;
158
+ SectionType currentSectionType = UndefinedSectionType;
159
+ BlockIterator currentBlock = begin;
160
+ while (currentBlock != end) {
161
+
162
+ currentSectionType = ClassifyBlock<T>(currentBlock, end, currentSectionType);
163
+ BlueprintSection currentSection(currentSectionType, std::make_pair(begin, end), parentSection);
164
+
165
+ ParseSectionResult sectionResult = P::ParseSection(currentSection,
166
+ currentBlock,
167
+ parser,
168
+ output);
169
+
170
+ result += sectionResult.first;
171
+ if (result.error.code != Error::OK)
172
+ break;
173
+
174
+ if (sectionResult.second == currentBlock)
175
+ break;
176
+
177
+ currentBlock = sectionResult.second;
178
+
179
+ if (currentSectionType == UndefinedSectionType)
180
+ break;
181
+ }
182
+
183
+ P::Finalize(std::make_pair(begin, currentBlock), parser, output, result);
184
+
185
+ return std::make_pair(result, currentBlock);
186
+ }
187
+ };
188
+ }
189
+
190
+ #endif