redsnow 0.1.6 → 0.2.0

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -0
  3. data/ext/snowcrash/Makefile +1 -1
  4. data/ext/snowcrash/bin/snowcrash +0 -0
  5. data/ext/snowcrash/configure +9 -9
  6. data/ext/snowcrash/ext/markdown-parser/Makefile +87 -0
  7. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/CONTRIBUTING.md +0 -0
  8. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/Makefile +2 -1
  9. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/Makefile.win +0 -0
  10. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/examples/smartypants.c +0 -0
  11. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/examples/sundown.c +0 -0
  12. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini.h +0 -0
  13. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini_href_e.c +0 -0
  14. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini_html_e.c +0 -0
  15. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html.c +0 -0
  16. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html.h +0 -0
  17. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html_smartypants.c +0 -0
  18. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html_block_names.txt +0 -0
  19. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/autolink.c +0 -0
  20. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/autolink.h +0 -0
  21. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/buffer.c +0 -0
  22. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/buffer.h +1 -1
  23. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/html_blocks.h +0 -0
  24. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/markdown.c +9 -3
  25. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/markdown.h +0 -0
  26. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/src_map.c +11 -7
  27. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/src_map.h +1 -1
  28. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/stack.c +0 -0
  29. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/stack.h +0 -0
  30. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/sundown.def +0 -0
  31. data/ext/snowcrash/ext/markdown-parser/msvc/markdown/markdown.vcproj +188 -0
  32. data/ext/snowcrash/ext/markdown-parser/msvc/msvc.sln +38 -0
  33. data/ext/snowcrash/ext/markdown-parser/msvc/sundown/sundown.vcproj +206 -0
  34. data/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.cc +92 -0
  35. data/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.h +82 -0
  36. data/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.cc +152 -0
  37. data/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.h +103 -0
  38. data/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.cc +388 -0
  39. data/ext/snowcrash/{src → ext/markdown-parser/src}/MarkdownParser.h +43 -33
  40. data/ext/snowcrash/snowcrash.gyp +114 -63
  41. data/ext/snowcrash/src/ActionParser.h +334 -398
  42. data/ext/snowcrash/src/AssetParser.h +82 -171
  43. data/ext/snowcrash/src/Blueprint.h +7 -2
  44. data/ext/snowcrash/src/BlueprintParser.h +212 -286
  45. data/ext/snowcrash/src/BlueprintUtility.h +2 -2
  46. data/ext/snowcrash/src/CBlueprint.h +1 -1
  47. data/ext/snowcrash/src/CSourceAnnotation.cc +11 -11
  48. data/ext/snowcrash/src/CSourceAnnotation.h +9 -9
  49. data/ext/snowcrash/src/CodeBlockUtility.h +199 -149
  50. data/ext/snowcrash/src/HeadersParser.h +197 -0
  51. data/ext/snowcrash/src/ParameterParser.h +429 -0
  52. data/ext/snowcrash/src/ParametersParser.h +136 -211
  53. data/ext/snowcrash/src/PayloadParser.h +458 -562
  54. data/ext/snowcrash/src/Platform.h +0 -3
  55. data/ext/snowcrash/src/ResourceGroupParser.h +183 -164
  56. data/ext/snowcrash/src/ResourceParser.h +325 -493
  57. data/ext/snowcrash/src/Section.cc +42 -0
  58. data/ext/snowcrash/src/Section.h +47 -0
  59. data/ext/snowcrash/src/SectionParser.h +229 -0
  60. data/ext/snowcrash/src/SectionParserData.h +81 -0
  61. data/ext/snowcrash/src/SectionProcessor.h +211 -0
  62. data/ext/snowcrash/src/Signature.cc +74 -0
  63. data/ext/snowcrash/src/Signature.h +32 -0
  64. data/ext/snowcrash/src/SourceAnnotation.h +7 -20
  65. data/ext/snowcrash/src/StringUtility.h +30 -10
  66. data/ext/snowcrash/src/SymbolTable.h +7 -7
  67. data/ext/snowcrash/src/UriTemplateParser.cc +10 -10
  68. data/ext/snowcrash/src/UriTemplateParser.h +11 -14
  69. data/ext/snowcrash/src/ValuesParser.h +122 -0
  70. data/ext/snowcrash/src/Version.h +2 -2
  71. data/ext/snowcrash/src/csnowcrash.cc +5 -5
  72. data/ext/snowcrash/src/csnowcrash.h +3 -3
  73. data/ext/snowcrash/src/snowcrash.cc +74 -4
  74. data/ext/snowcrash/src/snowcrash.h +9 -4
  75. data/ext/snowcrash/src/snowcrash/snowcrash.cc +16 -16
  76. data/ext/snowcrash/tools/homebrew/snowcrash.rb +3 -2
  77. data/ext/snowcrash/vcbuild.bat +13 -4
  78. data/lib/redsnow.rb +5 -5
  79. data/lib/redsnow/binding.rb +1 -1
  80. data/lib/redsnow/blueprint.rb +33 -2
  81. data/lib/redsnow/parseresult.rb +7 -4
  82. data/lib/redsnow/version.rb +1 -1
  83. data/test/redsnow_binding_test.rb +6 -6
  84. data/test/redsnow_parseresult_test.rb +1 -1
  85. metadata +62 -42
  86. data/ext/snowcrash/src/BlockUtility.h +0 -186
  87. data/ext/snowcrash/src/BlueprintParserCore.h +0 -190
  88. data/ext/snowcrash/src/BlueprintSection.h +0 -140
  89. data/ext/snowcrash/src/DescriptionSectionUtility.h +0 -156
  90. data/ext/snowcrash/src/HeaderParser.h +0 -289
  91. data/ext/snowcrash/src/ListBlockUtility.h +0 -273
  92. data/ext/snowcrash/src/ListUtility.h +0 -95
  93. data/ext/snowcrash/src/MarkdownBlock.cc +0 -176
  94. data/ext/snowcrash/src/MarkdownBlock.h +0 -93
  95. data/ext/snowcrash/src/MarkdownParser.cc +0 -266
  96. data/ext/snowcrash/src/ParameterDefinitonParser.h +0 -645
  97. data/ext/snowcrash/src/Parser.cc +0 -71
  98. data/ext/snowcrash/src/Parser.h +0 -29
  99. data/ext/snowcrash/src/ParserCore.cc +0 -120
  100. data/ext/snowcrash/src/ParserCore.h +0 -82
  101. data/ext/snowcrash/src/SectionUtility.h +0 -142
@@ -9,207 +9,118 @@
9
9
  #ifndef SNOWCRASH_ASSETPARSER_H
10
10
  #define SNOWCRASH_ASSETPARSER_H
11
11
 
12
- #include <sstream>
13
- #include "BlueprintParserCore.h"
14
- #include "Blueprint.h"
12
+ #include "SectionParser.h"
15
13
  #include "RegexMatch.h"
16
- #include "StringUtility.h"
17
- #include "SectionUtility.h"
18
-
19
- namespace snowcrashconst {
20
-
21
- /** Body matching regex */
22
- const char* const BodyRegex("^[[:blank:]]*[Bb]ody[[:blank:]]*$");
23
-
24
- /** Schema matching regex */
25
- const char* const SchemaRegex("^[[:blank:]]*[Ss]chema[[:blank:]]*$");
26
- }
14
+ #include "CodeBlockUtility.h"
27
15
 
28
16
  namespace snowcrash {
29
17
 
30
18
  /// Asset signature
31
19
  enum AssetSignature {
32
- UndefinedAssetSignature,
33
- NoAssetSignature,
20
+ NoAssetSignature = 0,
34
21
  BodyAssetSignature, /// < Explicit body asset
35
- PayloadBodyAssetSignature, /// < Body asset using abbreviated syntax
22
+ ImplicitBodyAssetSignature, /// < Body asset using abbreviated syntax
36
23
  SchemaAssetSignature, /// < Explicit Schema asset
37
- GenericAssetSignature
24
+ UndefinedAssetSignature = -1
38
25
  };
39
26
 
40
- // Query asset signature a of given block
41
- FORCEINLINE AssetSignature GetAssetSignature(const BlockIterator& begin,
42
- const BlockIterator& end) {
43
-
44
- if (begin->type == ListBlockBeginType || begin->type == ListItemBlockBeginType) {
45
-
46
- BlockIterator cur = ListItemNameBlock(begin, end);
47
- if (cur == end)
48
- return NoAssetSignature;
49
-
50
- if (cur->type != ParagraphBlockType &&
51
- cur->type != ListItemBlockEndType)
52
- return NoAssetSignature;
53
-
54
- std::string content = GetFirstLine(cur->content);
55
- if (RegexMatch(content, snowcrashconst::BodyRegex))
56
- return BodyAssetSignature;
27
+ /** Body matching regex */
28
+ const char* const BodyRegex = "^[[:blank:]]*[Bb]ody[[:blank:]]*$";
29
+
30
+ /** Schema matching regex */
31
+ const char* const SchemaRegex = "^[[:blank:]]*[Ss]chema[[:blank:]]*$";
57
32
 
58
- if (RegexMatch(content, snowcrashconst::SchemaRegex))
59
- return SchemaAssetSignature;
60
-
61
- if (HasPayloadAssetSignature(begin, end))
62
- return PayloadBodyAssetSignature;
63
- }
64
-
65
- return NoAssetSignature;
66
- }
67
-
68
- FORCEINLINE bool HasAssetSignature(const BlockIterator& begin,
69
- const BlockIterator& end) {
70
- AssetSignature signature = GetAssetSignature(begin, end);
71
- return (signature != NoAssetSignature);
72
- }
73
-
74
- /**
75
- * Return true if given block might be a dangling asset block,
76
- * false otherwise.
77
- */
78
- FORCEINLINE bool IsDanglingBlock(const BlockIterator& begin, const BlockIterator& end) {
79
- return (begin->type == ParagraphBlockType
80
- || begin->type == CodeBlockType);
81
- }
82
-
83
33
  /**
84
- * Block Classifier, asset context.
34
+ * Asset Section Processor
85
35
  */
86
- template <>
87
- FORCEINLINE SectionType ClassifyBlock<Asset>(const BlockIterator& begin,
88
- const BlockIterator& end,
89
- const SectionType& context) {
36
+ template<>
37
+ struct SectionProcessor<Asset> : public SectionProcessorBase<Asset> {
90
38
 
91
- if (context == UndefinedSectionType) {
92
- AssetSignature asset = GetAssetSignature(begin, end);
93
- if (asset == BodyAssetSignature || asset == PayloadBodyAssetSignature)
94
- return BodySectionType;
95
- if (asset == SchemaAssetSignature)
96
- return SchemaSectionType;
97
- }
98
- else if (context == BodySectionType ||
99
- context == SchemaSectionType) {
100
-
101
- // SectionType closure
102
- if (begin->type == ListItemBlockEndType ||
103
- begin->type == ListBlockEndType) {
104
-
105
- // Look ahead for a dangling asset
106
- BlockIterator cur = CloseNestedList(begin, end);
107
- if (cur == end)
108
- return UndefinedSectionType;
109
-
110
- if (IsDanglingBlock(cur, end))
111
- return (context == BodySectionType) ? DanglingBodySectionType : DanglingSchemaSectionType;
112
- else
113
- return UndefinedSectionType;
114
- }
39
+ static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
40
+ const MarkdownNodes& siblings,
41
+ SectionParserData& pd,
42
+ SectionLayout& layout,
43
+ Report& report,
44
+ Asset& out) {
115
45
 
116
- // Adjacent list item
117
- if (begin->type == ListItemBlockBeginType) {
118
- return UndefinedSectionType;
119
- }
46
+ out = "";
47
+ CodeBlockUtility::signatureContentAsCodeBlock(node, pd, report, out);
48
+ return ++MarkdownNodeIterator(node);
120
49
  }
121
- else if (context == DanglingBodySectionType ||
122
- context == DanglingSchemaSectionType) {
50
+
51
+ static MarkdownNodeIterator processDescription(const MarkdownNodeIterator& node,
52
+ const MarkdownNodes& siblings,
53
+ SectionParserData& pd,
54
+ Report& report,
55
+ Asset& out) {
56
+ return node;
57
+ }
58
+
59
+ static MarkdownNodeIterator processContent(const MarkdownNodeIterator& node,
60
+ const MarkdownNodes& siblings,
61
+ SectionParserData& pd,
62
+ Report& report,
63
+ Asset& out) {
123
64
 
124
- if (begin->type == ListItemBlockEndType ||
125
- begin->type == ListBlockEndType)
126
- return UndefinedSectionType;
127
65
 
128
- if (!IsDanglingBlock(begin, end))
129
- return UndefinedSectionType;
66
+ mdp::ByteBuffer content;
67
+ CodeBlockUtility::contentAsCodeBlock(node, pd, report, content);
68
+ out += content;
69
+ return ++MarkdownNodeIterator(node);
130
70
  }
131
71
 
132
- return (context == BodySectionType ||
133
- context == SchemaSectionType ||
134
- context == DanglingBodySectionType ||
135
- context == DanglingSchemaSectionType) ? context : UndefinedSectionType;
136
- }
137
-
138
- //
139
- // Asset SectionType Parser
140
- //
141
- template<>
142
- struct SectionParser<Asset> {
143
-
144
- static ParseSectionResult ParseSection(const BlueprintSection& section,
145
- const BlockIterator& cur,
146
- BlueprintParserCore& parser,
147
- Asset& asset) {
148
-
149
- ParseSectionResult result = std::make_pair(Result(), cur);
150
- switch (section.type) {
151
- case BodySectionType:
152
- case SchemaSectionType:
153
- result = HandleAssetSectionBlock(section, cur, parser, asset);
154
- break;
155
-
156
- case DanglingBodySectionType:
157
- case DanglingSchemaSectionType:
158
- result = HandleDanglingAssetSectionBlock(section, cur, parser, asset);
159
- break;
160
-
161
- case UndefinedSectionType:
162
- result.second = CloseList(cur, section.bounds.second);
163
- break;
164
-
165
- default:
166
- result.first.error = UnexpectedBlockError(section, cur, parser.sourceData);
167
- break;
168
- }
169
-
170
- return result;
72
+ static bool isDescriptionNode(const MarkdownNodeIterator& node,
73
+ SectionType sectionType) {
74
+ return false;
171
75
  }
172
76
 
173
- static void Finalize(const SectionBounds& bounds,
174
- BlueprintParserCore& parser,
175
- Asset& asset,
176
- Result& result) {}
77
+ static bool isContentNode(const MarkdownNodeIterator& node,
78
+ SectionType sectionType) {
79
+
80
+ return (SectionKeywordSignature(node) == UndefinedSectionType);
81
+ }
177
82
 
178
- static ParseSectionResult HandleAssetSectionBlock(const BlueprintSection& section,
179
- const BlockIterator& cur,
180
- BlueprintParserCore& parser,
181
- Asset& asset) {
83
+ static SectionType sectionType(const MarkdownNodeIterator& node) {
84
+ if (node->type == mdp::ListItemMarkdownNodeType
85
+ && !node->children().empty()) {
182
86
 
183
- SourceData data;
184
- SourceDataBlock sourceMap;
185
- // NOTE: Use `Payload` traits for parsing pre-formatted list block.
186
- ParseSectionResult result = ParseListPreformattedBlock<Payload>(section,
187
- cur,
188
- parser,
189
- data,
190
- sourceMap);
191
- if (result.first.error.code != Error::OK ||
192
- parser.sourceData.empty())
193
- return result;
194
-
195
- asset += data;
196
- return result;
87
+ AssetSignature signature = assetSignature(node);
88
+
89
+ switch (signature) {
90
+ case BodyAssetSignature:
91
+ case ImplicitBodyAssetSignature:
92
+ return BodySectionType;
93
+
94
+ case SchemaAssetSignature:
95
+ return SchemaSectionType;
96
+
97
+ default:
98
+ return UndefinedSectionType;
99
+ }
100
+ }
101
+
102
+ return UndefinedSectionType;
197
103
  }
198
104
 
199
- static ParseSectionResult HandleDanglingAssetSectionBlock(const BlueprintSection& section,
200
- const BlockIterator& cur,
201
- BlueprintParserCore& parser,
202
- Asset& asset) {
105
+ /** Resolve asset signature */
106
+ static AssetSignature assetSignature(const MarkdownNodeIterator& node) {
107
+
108
+ mdp::ByteBuffer remaining, subject = node->children().front().text;
109
+ subject = GetFirstLine(subject, remaining);
110
+ TrimString(subject);
203
111
 
204
- // Skip any closing list blocks
205
- BlockIterator sectionCur = CloseNestedList(cur, section.bounds.second);
206
- return HandleAssetSectionBlock(section, sectionCur, parser, asset);
207
- }
112
+ if (RegexMatch(subject, BodyRegex))
113
+ return BodyAssetSignature;
208
114
 
115
+ if (RegexMatch(subject, SchemaRegex))
116
+ return SchemaAssetSignature;
117
+
118
+ return NoAssetSignature;
119
+ }
209
120
  };
210
121
 
211
- typedef BlockParser<Asset, SectionParser<Asset> > AssetParser;
212
-
122
+ /** Asset Section Parser */
123
+ typedef SectionParser<Asset, ListSectionAdapter> AssetParser;
213
124
  }
214
125
 
215
126
  #endif
@@ -48,7 +48,7 @@ namespace snowcrash {
48
48
 
49
49
  /** Parameter Value */
50
50
  typedef std::string Value;
51
-
51
+
52
52
  /** A generic key - value pair */
53
53
  typedef std::pair<std::string, std::string> KeyValuePair;
54
54
 
@@ -113,6 +113,8 @@ namespace snowcrash {
113
113
  Collection<Value>::type values;
114
114
  };
115
115
 
116
+ /** Name of a symbol */
117
+ typedef std::string SymbolName;
116
118
 
117
119
  /**
118
120
  * Payload
@@ -136,6 +138,9 @@ namespace snowcrash {
136
138
 
137
139
  /** Schema */
138
140
  Asset schema;
141
+
142
+ /** Symbol */
143
+ SymbolName symbol;
139
144
  };
140
145
 
141
146
  /** Resource Model */
@@ -257,7 +262,7 @@ namespace snowcrash {
257
262
  /** Resources */
258
263
  Collection<Resource>::type resources;
259
264
  };
260
-
265
+
261
266
  /**
262
267
  * \brief API Blueprint AST
263
268
  *
@@ -9,339 +9,265 @@
9
9
  #ifndef SNOWCRASH_BLUEPRINTPARSER_H
10
10
  #define SNOWCRASH_BLUEPRINTPARSER_H
11
11
 
12
- #include <functional>
13
- #include <sstream>
14
- #include <iterator>
15
- #include "Blueprint.h"
16
- #include "BlueprintParserCore.h"
17
12
  #include "ResourceParser.h"
18
13
  #include "ResourceGroupParser.h"
14
+ #include "SectionParser.h"
15
+ #include "RegexMatch.h"
16
+ #include "CodeBlockUtility.h"
17
+
18
+ namespace snowcrash {
19
19
 
20
- namespace snowcrashconst {
21
-
22
20
  const char* const ExpectedAPINameMessage = "expected API name, e.g. '# <API Name>'";
23
- }
24
21
 
25
- namespace snowcrash {
22
+ /** Internal type alias for Collection of Metadata */
23
+ typedef Collection<Metadata>::type MetadataCollection;
26
24
 
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 */
25
+ typedef Collection<Metadata>::iterator MetadataCollectionIterator;
26
+
27
+ /**
28
+ * Blueprint processor
29
+ */
49
30
  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;
31
+ struct SectionProcessor<Blueprint> : public SectionProcessorBase<Blueprint> {
32
+
33
+ static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
34
+ const MarkdownNodes& siblings,
35
+ SectionParserData& pd,
36
+ SectionLayout& layout,
37
+ Report& report,
38
+ Blueprint& out) {
39
+
40
+ MarkdownNodeIterator cur = node;
41
+
42
+ while (cur != siblings.end() &&
43
+ cur->type == mdp::ParagraphMarkdownNodeType) {
44
+
45
+ MetadataCollection metadata;
46
+ parseMetadata(cur, pd, report, metadata);
47
+
48
+ // First block is paragraph and is not metadata (no API name)
49
+ if (metadata.empty()) {
50
+ return processDescription(cur, siblings, pd, report, out);
51
+ } else {
52
+ out.metadata.insert(out.metadata.end(), metadata.begin(), metadata.end());
53
+ }
54
+
55
+ cur++;
72
56
  }
73
57
 
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;
58
+ // Ideally this parsing metadata should be handled by separate parser
59
+ // that way the following check would be covered in SectionParser::parse()
60
+ if (cur == siblings.end())
61
+ return cur;
62
+
63
+ if (cur->type == mdp::HeaderMarkdownNodeType) {
64
+
65
+ SectionType nestedType = nestedSectionType(cur);
66
+
67
+ // Resources Groups only, parse as exclusive nested sections
68
+ if (nestedType != UndefinedSectionType) {
69
+ layout = ExclusiveNestedSectionLayout;
70
+ return cur;
71
+ }
72
+
73
+ out.name = cur->text;
74
+ TrimString(out.name);
75
+ } else {
76
+
77
+ // Any other type of block, add to description
78
+ return processDescription(cur, siblings, pd, report, out);
105
79
  }
106
80
 
107
- // WARN: No API name specified
108
- result.warnings.push_back(Warning(snowcrashconst::ExpectedAPINameMessage,
109
- APINameWarning,
110
- MapSourceDataBlock(cur->sourceMap, parser.sourceData)));
81
+ return ++MarkdownNodeIterator(cur);
82
+ }
111
83
 
112
- return true;
84
+ static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
85
+ const MarkdownNodes& siblings,
86
+ SectionParserData& pd,
87
+ Report& report,
88
+ Blueprint& out) {
89
+
90
+ if (pd.sectionContext() == ResourceGroupSectionType ||
91
+ pd.sectionContext() == ResourceSectionType) {
92
+
93
+ ResourceGroup resourceGroup;
94
+ MarkdownNodeIterator cur = ResourceGroupParser::parse(node, siblings, pd, report, resourceGroup);
95
+
96
+ ResourceGroupIterator duplicate = findResourceGroup(out.resourceGroups, resourceGroup);
97
+
98
+ if (duplicate != out.resourceGroups.end()) {
99
+
100
+ // WARN: duplicate resource group
101
+ std::stringstream ss;
102
+
103
+ if (resourceGroup.name.empty()) {
104
+ ss << "anonymous group";
105
+ } else {
106
+ ss << "group '" << resourceGroup.name << "'";
107
+ }
108
+
109
+ ss << " is already defined";
110
+
111
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
112
+ report.warnings.push_back(Warning(ss.str(),
113
+ DuplicateWarning,
114
+ sourceMap));
115
+ }
116
+
117
+ out.resourceGroups.push_back(resourceGroup);
118
+
119
+ return cur;
120
+ }
121
+
122
+ return node;
113
123
  }
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;
124
+
125
+ static SectionType sectionType(const MarkdownNodeIterator& node) {
126
+
127
+ return BlueprintSectionType;
125
128
  }
126
129
 
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);
130
+ static SectionType nestedSectionType(const MarkdownNodeIterator& node) {
134
131
 
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);
132
+ SectionType nestedType = UndefinedSectionType;
144
133
 
145
- // Check Name
146
- if (!CheckBlueprintName(sectionCur, output, parser, result.first))
147
- return result;
148
-
149
- result.second = ++sectionCur;
150
- return result;
134
+ // Check if Resource section
135
+ nestedType = SectionProcessor<Resource>::sectionType(node);
136
+
137
+ if (nestedType != UndefinedSectionType) {
138
+ return nestedType;
151
139
  }
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;
140
+
141
+ // Check if ResourceGroup section
142
+ nestedType = SectionProcessor<ResourceGroup>::sectionType(node);
143
+
144
+ if (nestedType != UndefinedSectionType) {
145
+ return nestedType;
160
146
  }
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;
147
+
148
+ return UndefinedSectionType;
170
149
  }
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;
150
+
151
+ static SectionTypes nestedSectionTypes() {
152
+ SectionTypes nested;
153
+
154
+ // Resource Group & descendants
155
+ nested.push_back(ResourceGroupSectionType);
156
+ SectionTypes types = SectionProcessor<ResourceGroup>::nestedSectionTypes();
157
+ nested.insert(nested.end(), types.begin(), types.end());
158
+
159
+ return nested;
160
+ }
161
+
162
+ static void finalize(const MarkdownNodeIterator& node,
163
+ SectionParserData& pd,
164
+ Report& report,
165
+ Blueprint& out) {
194
166
 
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";
167
+ if (!out.name.empty())
168
+ return;
169
+
170
+ if (pd.options & RequireBlueprintNameOption) {
171
+
172
+ // ERR: No API name specified
173
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
174
+ report.error = Error(ExpectedAPINameMessage,
175
+ BusinessError,
176
+ sourceMap);
207
177
 
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
178
  }
213
-
214
- output.resourceGroups.push_back(resourceGroup); // FIXME: C++11 move
215
- return result;
179
+ else if (!out.description.empty()) {
180
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
181
+ report.warnings.push_back(Warning(ExpectedAPINameMessage,
182
+ APINameWarning,
183
+ sourceMap));
184
+ }
216
185
  }
217
-
218
186
 
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;
187
+ static bool isUnexpectedNode(const MarkdownNodeIterator& node,
188
+ SectionType sectionType) {
227
189
 
228
- ParseSectionResult result = std::make_pair(Result(), cur);
229
- SourceData content = cur->content;
190
+ // Since Blueprint is currently top-level node any unprocessed node should be reported
191
+ return true;
192
+ }
193
+
194
+
195
+ static void parseMetadata(const MarkdownNodeIterator& node,
196
+ SectionParserData& pd,
197
+ Report& report,
198
+ MetadataCollection& out) {
199
+
200
+ mdp::ByteBuffer content = node->text;
230
201
  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
-
202
+
203
+ std::vector<mdp::ByteBuffer> lines = Split(content, '\n');
204
+
205
+ for (std::vector<mdp::ByteBuffer>::iterator it = lines.begin();
206
+ it != lines.end();
207
+ ++it) {
208
+
236
209
  Metadata metadata;
237
- if (KeyValueFromLine(*line, metadata))
238
- metadataCollection.push_back(metadata);
210
+
211
+ if (CodeBlockUtility::keyValueFromLine(*it, metadata)) {
212
+ out.push_back(metadata);
213
+ }
239
214
  }
240
-
241
- if (lines.size() == metadataCollection.size()) {
242
-
215
+
216
+ if (lines.size() == out.size()) {
217
+
243
218
  // Check duplicates
244
- std::vector<std::string> duplicateKeys;
245
- for (MetadataCollectionIterator it = metadataCollection.begin();
246
- it != metadataCollection.end();
219
+ std::vector<mdp::ByteBuffer> duplicateKeys;
220
+
221
+ for (MetadataCollectionIterator it = out.begin();
222
+ it != out.end();
247
223
  ++it) {
248
-
224
+
249
225
  MetadataCollectionIterator from = it;
250
- if (++from == metadataCollection.end())
226
+ if (++from == out.end())
251
227
  break;
252
-
228
+
253
229
  MetadataCollectionIterator duplicate = std::find_if(from,
254
- metadataCollection.end(),
230
+ out.end(),
255
231
  std::bind2nd(MatchFirsts<Metadata>(), *it));
256
-
257
- if (duplicate != metadataCollection.end() &&
232
+
233
+ if (duplicate != out.end() &&
258
234
  std::find(duplicateKeys.begin(), duplicateKeys.end(), it->first) == duplicateKeys.end()) {
259
-
235
+
260
236
  duplicateKeys.push_back(it->first);
261
-
262
- // WARN: duplicate metada definition
237
+
238
+ // WARN: duplicate metadata definition
263
239
  std::stringstream ss;
264
240
  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));
241
+
242
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
243
+ report.warnings.push_back(Warning(ss.str(),
244
+ DuplicateWarning,
245
+ sourceMap));
270
246
  }
271
247
  }
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
248
  }
280
- else if (!metadataCollection.empty()) {
249
+ else if (!out.empty()) {
250
+
281
251
  // 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));
252
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
253
+ report.warnings.push_back(Warning("ignoring possible metadata, expected '<key> : <value>', one one per line",
254
+ FormattingWarning,
255
+ sourceMap));
287
256
  }
288
-
289
- return result;
290
257
  }
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
- }
258
+
259
+ /** Finds a resource group inside an resource groups collection */
260
+ static ResourceGroupIterator findResourceGroup(const ResourceGroups& resourceGroups,
261
+ const ResourceGroup& resourceGroup) {
262
+
263
+ return std::find_if(resourceGroups.begin(),
264
+ resourceGroups.end(),
265
+ std::bind2nd(MatchName<ResourceGroup>(), resourceGroup));
343
266
  }
344
267
  };
268
+
269
+ /** Blueprint Parser */
270
+ typedef SectionParser<Blueprint, BlueprintSectionAdapter> BlueprintParser;
345
271
  }
346
272
 
347
273
  #endif