redsnow 0.1.6 → 0.2.0

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