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
@@ -0,0 +1,197 @@
1
+ //
2
+ // HeaderParser.h
3
+ // snowcrash
4
+ //
5
+ // Created by Zdenek Nemec on 5/22/13.
6
+ // Copyright (c) 2013 Apiary Inc. All rights reserved.
7
+ //
8
+
9
+ #ifndef SNOWCRASH_HEADERPARSER_H
10
+ #define SNOWCRASH_HEADERPARSER_H
11
+
12
+ #include "SectionParser.h"
13
+ #include "RegexMatch.h"
14
+ #include "CodeBlockUtility.h"
15
+ #include "StringUtility.h"
16
+ #include "BlueprintUtility.h"
17
+
18
+ namespace snowcrash {
19
+
20
+ /** Headers matching regex */
21
+ const char* const HeadersRegex = "^[[:blank:]]*[Hh]eaders?[[:blank:]]*$";
22
+
23
+ /** Internal type alias for collection of HTTP headers */
24
+ typedef Collection<Header>::type Headers;
25
+
26
+ /** Header Iterator in its containment group */
27
+ typedef Collection<Header>::const_iterator HeaderIterator;
28
+
29
+ /**
30
+ * Headers Section Processor
31
+ */
32
+ template<>
33
+ struct SectionProcessor<Headers> : public SectionProcessorBase<Headers> {
34
+
35
+ static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
36
+ const MarkdownNodes& siblings,
37
+ SectionParserData& pd,
38
+ SectionLayout& layout,
39
+ Report& report,
40
+ Headers& out) {
41
+
42
+ mdp::ByteBuffer content;
43
+ CodeBlockUtility::signatureContentAsCodeBlock(node, pd, report, content);
44
+
45
+ headersFromContent(node, content, pd, report, out);
46
+
47
+ return ++MarkdownNodeIterator(node);
48
+ }
49
+
50
+ static MarkdownNodeIterator processDescription(const MarkdownNodeIterator& node,
51
+ const MarkdownNodes& siblings,
52
+ SectionParserData& pd,
53
+ Report& report,
54
+ Headers& out) {
55
+ return node;
56
+ }
57
+
58
+ static MarkdownNodeIterator processContent(const MarkdownNodeIterator& node,
59
+ const MarkdownNodes& siblings,
60
+ SectionParserData& pd,
61
+ Report& report,
62
+ Headers& out) {
63
+
64
+ mdp::ByteBuffer content;
65
+ CodeBlockUtility::contentAsCodeBlock(node, pd, report, content);
66
+
67
+ headersFromContent(node, content, pd, report, out);
68
+
69
+ return ++MarkdownNodeIterator(node);
70
+ }
71
+
72
+ static bool isDescriptionNode(const MarkdownNodeIterator& node,
73
+ SectionType sectionType) {
74
+ return false;
75
+ }
76
+
77
+ static bool isContentNode(const MarkdownNodeIterator& node,
78
+ SectionType sectionType) {
79
+
80
+ return (SectionKeywordSignature(node) == UndefinedSectionType);
81
+ }
82
+
83
+ static SectionType sectionType(const MarkdownNodeIterator& node) {
84
+
85
+ if (node->type == mdp::ListItemMarkdownNodeType
86
+ && !node->children().empty()) {
87
+
88
+ mdp::ByteBuffer subject = node->children().front().text;
89
+ mdp::ByteBuffer signature;
90
+ mdp::ByteBuffer remainingContent;
91
+
92
+ signature = GetFirstLine(subject, remainingContent);
93
+ TrimString(signature);
94
+
95
+ if (RegexMatch(signature, HeadersRegex))
96
+ return HeadersSectionType;
97
+ }
98
+
99
+ return UndefinedSectionType;
100
+ }
101
+
102
+ static void finalize(const MarkdownNodeIterator& node,
103
+ SectionParserData& pd,
104
+ Report& report,
105
+ Headers& out) {
106
+
107
+ if (out.empty()) {
108
+
109
+ // WARN: No headers defined
110
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
111
+ report.warnings.push_back(Warning("no headers specified",
112
+ FormattingWarning,
113
+ sourceMap));
114
+ }
115
+ }
116
+
117
+ /** Retrieve headers from content */
118
+ static void headersFromContent(const MarkdownNodeIterator& node,
119
+ const mdp::ByteBuffer& content,
120
+ SectionParserData& pd,
121
+ Report& report,
122
+ Headers& headers) {
123
+ std::vector<std::string> lines = Split(content, '\n');
124
+
125
+ for (std::vector<std::string>::iterator line = lines.begin();
126
+ line != lines.end();
127
+ ++line) {
128
+ if (TrimString(*line).empty()) {
129
+ continue;
130
+ }
131
+
132
+ Header header;
133
+
134
+ if (CodeBlockUtility::keyValueFromLine(*line, header)) {
135
+ if (findHeader(headers, header) != headers.end()) {
136
+ // WARN: duplicate header on this level
137
+ std::stringstream ss;
138
+
139
+ ss << "duplicate definition of '" << header.first << "' header";
140
+
141
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
142
+ report.warnings.push_back(Warning(ss.str(),
143
+ DuplicateWarning,
144
+ sourceMap));
145
+ }
146
+
147
+ headers.push_back(header);
148
+ } else {
149
+ // WARN: unable to parse header
150
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
151
+ report.warnings.push_back(Warning("unable to parse HTTP header, expected '<header name> : <header value>', one header per line",
152
+ FormattingWarning,
153
+ sourceMap));
154
+ }
155
+ }
156
+ }
157
+
158
+ /** Inject headers into transaction examples requests and responses */
159
+ static void injectDeprecatedHeaders(const Headers& headers,
160
+ Collection<TransactionExample>::type& examples) {
161
+
162
+ for (Collection<TransactionExample>::iterator exampleIt = examples.begin();
163
+ exampleIt != examples.end();
164
+ ++exampleIt) {
165
+
166
+ // Requests
167
+ for (Collection<Request>::iterator reqIt = exampleIt->requests.begin();
168
+ reqIt != exampleIt->requests.end();
169
+ ++reqIt) {
170
+
171
+ reqIt->headers.insert(reqIt->headers.begin(), headers.begin(), headers.end());
172
+ }
173
+
174
+ // Responses
175
+ for (Collection<Response>::iterator resIt = exampleIt->responses.begin();
176
+ resIt != exampleIt->responses.end();
177
+ ++resIt) {
178
+
179
+ resIt->headers.insert(resIt->headers.begin(), headers.begin(), headers.end());
180
+ }
181
+ }
182
+ }
183
+
184
+ /** Finds a header in its containment group by its key (first) */
185
+ static HeaderIterator findHeader(const Headers& headers,
186
+ const Header& header) {
187
+ return std::find_if(headers.begin(),
188
+ headers.end(),
189
+ std::bind2nd(MatchFirsts<Header>(), header));
190
+ }
191
+ };
192
+
193
+ /** Headers Section Parser */
194
+ typedef SectionParser<Headers, ListSectionAdapter> HeadersParser;
195
+ }
196
+
197
+ #endif
@@ -0,0 +1,429 @@
1
+ //
2
+ // ParameterParser.h
3
+ // snowcrash
4
+ //
5
+ // Created by Zdenek Nemec on 9/1/13.
6
+ // Copyright (c) 2013 Apiary Inc. All rights reserved.
7
+ //
8
+
9
+ #ifndef SNOWCRASH_PARAMETERPARSER_H
10
+ #define SNOWCRASH_PARAMETERPARSER_H
11
+
12
+ #include "SectionParser.h"
13
+ #include "ValuesParser.h"
14
+ #include "RegexMatch.h"
15
+ #include "StringUtility.h"
16
+
17
+ /** Parameter Value regex */
18
+ #define PARAMETER_VALUE "`([^`]+)`"
19
+
20
+ /** Parameter Identifier */
21
+ #define PARAMETER_IDENTIFIER "(([[:alnum:]_.-])*|(%[A-Fa-f0-9]{2})*)+"
22
+
23
+ /** Lead in and out for comma separated values regex */
24
+ #define CSV_LEADINOUT "[[:blank:]]*,?[[:blank:]]*"
25
+
26
+ namespace snowcrash {
27
+
28
+ /** Parameter Required matching regex */
29
+ const char* const ParameterRequiredRegex = "^[[:blank:]]*[Rr]equired[[:blank:]]*$";
30
+
31
+ /** Parameter Optional matching regex */
32
+ const char* const ParameterOptionalRegex = "^[[:blank:]]*[Oo]ptional[[:blank:]]*$";
33
+
34
+ /** Additonal Parameter Traits Example matching regex */
35
+ const char* const AdditionalTraitsExampleRegex = CSV_LEADINOUT "`([^`]*)`" CSV_LEADINOUT;
36
+
37
+ /** Additonal Parameter Traits Use matching regex */
38
+ const char* const AdditionalTraitsUseRegex = CSV_LEADINOUT "([Oo]ptional|[Rr]equired)" CSV_LEADINOUT;
39
+
40
+ /** Additonal Parameter Traits Type matching regex */
41
+ const char* const AdditionalTraitsTypeRegex = CSV_LEADINOUT "([^,]*)" CSV_LEADINOUT;
42
+
43
+ /** Parameter Values matching regex */
44
+ const char* const ParameterValuesRegex = "^[[:blank:]]*[Vv]alues[[:blank:]]*$";
45
+
46
+ /** Values expected content */
47
+ const char* const ExpectedValuesContent = "nested list of possible parameter values, one element per list item e.g. '`value`'";
48
+
49
+ /** Parameter description delimiter */
50
+ const std::string DescriptionIdentifier = "...";
51
+
52
+ /**
53
+ * Parameter section processor
54
+ */
55
+ template<>
56
+ struct SectionProcessor<Parameter> : public SectionProcessorBase<Parameter> {
57
+
58
+ static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
59
+ const MarkdownNodes& siblings,
60
+ SectionParserData& pd,
61
+ SectionLayout& layout,
62
+ Report& report,
63
+ Parameter& out) {
64
+
65
+ mdp::ByteBuffer signature, remainingContent;
66
+ signature = GetFirstLine(node->text, remainingContent);
67
+
68
+ parseSignature(node, pd, signature, report, out);
69
+
70
+ if (!remainingContent.empty()) {
71
+ out.description += "\n" + remainingContent + "\n";
72
+ }
73
+
74
+ return ++MarkdownNodeIterator(node);
75
+ }
76
+
77
+
78
+ static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
79
+ const MarkdownNodes& siblings,
80
+ SectionParserData& pd,
81
+ Report& report,
82
+ Parameter& out) {
83
+
84
+ if (pd.sectionContext() != ValuesSectionType) {
85
+ return node;
86
+ }
87
+
88
+ // Check redefinition
89
+ if (!out.values.empty()) {
90
+ // WARN: parameter values are already defined
91
+ std::stringstream ss;
92
+ ss << "overshadowing previous 'values' definition";
93
+ ss << " for parameter '" << out.name << "'";
94
+
95
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
96
+ report.warnings.push_back(Warning(ss.str(),
97
+ RedefinitionWarning,
98
+ sourceMap));
99
+ }
100
+
101
+ // Clear any previous values
102
+ out.values.clear();
103
+
104
+ ValuesParser::parse(node, siblings, pd, report, out.values);
105
+
106
+ if (out.values.empty()) {
107
+ // WARN: empty definition
108
+ std::stringstream ss;
109
+ ss << "no possible values specified for parameter '" << out.name << "'";
110
+
111
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
112
+ report.warnings.push_back(Warning(ss.str(),
113
+ EmptyDefinitionWarning,
114
+ sourceMap));
115
+ }
116
+
117
+ if ((!out.exampleValue.empty() || !out.defaultValue.empty()) &&
118
+ !out.values.empty()) {
119
+
120
+ checkExampleAndDefaultValue(node, pd, report, out);
121
+ }
122
+
123
+ return ++MarkdownNodeIterator(node);
124
+ }
125
+
126
+ static SectionType sectionType(const MarkdownNodeIterator& node) {
127
+
128
+ if (node->type == mdp::ListItemMarkdownNodeType
129
+ && !node->children().empty()) {
130
+
131
+ mdp::ByteBuffer subject, remainingContent;
132
+ subject = GetFirstLine(node->children().front().text, remainingContent);
133
+ TrimString(subject);
134
+
135
+ if (isValidParameterSignature(subject)) {
136
+ return ParameterSectionType;
137
+ }
138
+ }
139
+
140
+ return UndefinedSectionType;
141
+ }
142
+
143
+ static SectionType nestedSectionType(const MarkdownNodeIterator& node) {
144
+
145
+ return SectionProcessor<Values>::sectionType(node);
146
+ }
147
+
148
+ static SectionTypes nestedSectionTypes() {
149
+ SectionTypes nested;
150
+
151
+ nested.push_back(ValuesSectionType);
152
+
153
+ return nested;
154
+ }
155
+
156
+ static void parseSignature(const mdp::MarkdownNodeIterator& node,
157
+ SectionParserData& pd,
158
+ mdp::ByteBuffer& signature,
159
+ Report& report,
160
+ Parameter& parameter) {
161
+
162
+ parameter.use = UndefinedParameterUse;
163
+
164
+ TrimString(signature);
165
+
166
+ CaptureGroups captureGroups;
167
+
168
+ if (isValidParameterSignature(signature)) {
169
+
170
+ mdp::ByteBuffer innerSignature = signature;
171
+ innerSignature = TrimString(innerSignature);
172
+
173
+ size_t firstSpace = innerSignature.find(" ");
174
+
175
+ if (firstSpace == std::string::npos) {
176
+ // Name
177
+ parameter.name = signature;
178
+ }
179
+ else {
180
+ parameter.name = innerSignature.substr(0, firstSpace);
181
+ innerSignature = innerSignature.substr(firstSpace + 1);
182
+ size_t descriptionPos = innerSignature.find(snowcrash::DescriptionIdentifier);
183
+
184
+ if (descriptionPos != std::string::npos) {
185
+ // Description
186
+ parameter.description = innerSignature.substr(descriptionPos);
187
+ parameter.description = TrimString(parameter.description.replace(0, snowcrash::DescriptionIdentifier.length(), ""));
188
+ innerSignature = innerSignature.substr(0, descriptionPos);
189
+ innerSignature = TrimString(innerSignature);
190
+ }
191
+
192
+ size_t attributesPos = innerSignature.find("(");
193
+
194
+ if (attributesPos != std::string::npos) {
195
+ size_t endOfAttributesPos = innerSignature.find_last_of(")");
196
+
197
+ if (endOfAttributesPos - attributesPos > 1) {
198
+ std::string attributes = innerSignature.substr(attributesPos, endOfAttributesPos - attributesPos);
199
+ attributes = attributes.substr(1);
200
+ parseAdditionalTraits(node, pd, attributes, report, parameter);
201
+ innerSignature = innerSignature.substr(0, attributesPos);
202
+ innerSignature = TrimString(innerSignature);
203
+ }
204
+ }
205
+
206
+ if (innerSignature.length() > 0) {
207
+ // Remove =
208
+ parameter.defaultValue = innerSignature;
209
+ parameter.defaultValue.erase(std::remove(parameter.defaultValue.begin(), parameter.defaultValue.end(), '='), parameter.defaultValue.end());
210
+ parameter.defaultValue.erase(std::remove(parameter.defaultValue.begin(), parameter.defaultValue.end(), '`'), parameter.defaultValue.end());
211
+ parameter.defaultValue = TrimString(parameter.defaultValue);
212
+ }
213
+ }
214
+
215
+ // Check possible required vs default clash
216
+ if (parameter.use != OptionalParameterUse &&
217
+ !parameter.defaultValue.empty()) {
218
+
219
+ // WARN: Required vs default clash
220
+ std::stringstream ss;
221
+ ss << "specifying parameter '" << parameter.name << "' as required supersedes its default value"\
222
+ ", declare the parameter as 'optional' to specify its default value";
223
+
224
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
225
+ report.warnings.push_back(Warning(ss.str(),
226
+ LogicalErrorWarning,
227
+ sourceMap));
228
+ }
229
+ } else {
230
+ // ERR: unable to parse
231
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
232
+ report.error = Error("unable to parse parameter specification",
233
+ BusinessError,
234
+ sourceMap);
235
+ }
236
+ }
237
+
238
+ static void parseAdditionalTraits(const mdp::MarkdownNodeIterator& node,
239
+ SectionParserData& pd,
240
+ mdp::ByteBuffer& traits,
241
+ Report& report,
242
+ Parameter& parameter) {
243
+
244
+ TrimString(traits);
245
+
246
+ CaptureGroups captureGroups;
247
+
248
+ // Cherry pick example value, if any
249
+ if (RegexCapture(traits, AdditionalTraitsExampleRegex, captureGroups) &&
250
+ captureGroups.size() > 1) {
251
+
252
+ parameter.exampleValue = captureGroups[1];
253
+ std::string::size_type pos = traits.find(captureGroups[0]);
254
+
255
+ if (pos != std::string::npos) {
256
+ traits.replace(pos, captureGroups[0].length(), std::string());
257
+ }
258
+ }
259
+
260
+ captureGroups.clear();
261
+
262
+ // Cherry pick use attribute, if any
263
+ if (RegexCapture(traits, AdditionalTraitsUseRegex, captureGroups) &&
264
+ captureGroups.size() > 1) {
265
+
266
+ parameter.use = RegexMatch(captureGroups[1], ParameterOptionalRegex) ? OptionalParameterUse : RequiredParameterUse;
267
+ std::string::size_type pos = traits.find(captureGroups[0]);
268
+
269
+ if (pos != std::string::npos) {
270
+ traits.replace(pos, captureGroups[0].length(), std::string());
271
+ }
272
+ }
273
+
274
+ captureGroups.clear();
275
+
276
+ // Finish with type
277
+ if (RegexCapture(traits, AdditionalTraitsTypeRegex, captureGroups) &&
278
+ captureGroups.size() > 1) {
279
+
280
+ parameter.type = captureGroups[1];
281
+ std::string::size_type pos = traits.find(captureGroups[0]);
282
+
283
+ if (pos != std::string::npos) {
284
+ traits.replace(pos, captureGroups[0].length(), std::string());
285
+ }
286
+ }
287
+
288
+ // Check what is left
289
+ TrimString(traits);
290
+
291
+ if (!traits.empty()) {
292
+ // WARN: Additional parameters traits warning
293
+ std::stringstream ss;
294
+ ss << "unable to parse additional parameter traits";
295
+ ss << ", expected '([required | optional], [<type>], [`<example value>`])'";
296
+ ss << ", e.g. '(optional, string, `Hello World`)'";
297
+
298
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
299
+ report.warnings.push_back(Warning(ss.str(),
300
+ FormattingWarning,
301
+ sourceMap));
302
+
303
+ parameter.type.clear();
304
+ parameter.exampleValue.clear();
305
+ parameter.use = UndefinedParameterUse;
306
+ }
307
+ }
308
+
309
+ static void checkExampleAndDefaultValue(const mdp::MarkdownNodeIterator& node,
310
+ SectionParserData& pd,
311
+ Report& report,
312
+ Parameter& parameter) {
313
+
314
+ bool isExampleFound = false;
315
+ bool isDefaultFound = false;
316
+
317
+ std::stringstream ss;
318
+ bool printWarning = false;
319
+
320
+ for (Collection<Value>::iterator it = parameter.values.begin();
321
+ it != parameter.values.end();
322
+ ++it) {
323
+
324
+ if (parameter.exampleValue == *it) {
325
+ isExampleFound = true;
326
+ }
327
+
328
+ if (parameter.defaultValue == *it) {
329
+ isDefaultFound = true;
330
+ }
331
+ }
332
+
333
+ if(!parameter.exampleValue.empty() &&
334
+ !isExampleFound) {
335
+
336
+ // WARN: missing example in values.
337
+ ss << "the example value '" << parameter.exampleValue << "' of parameter '"<< parameter.name <<"' is not in its list of expected values";
338
+ printWarning = true;
339
+ }
340
+
341
+ if(!parameter.defaultValue.empty() &&
342
+ !isDefaultFound) {
343
+
344
+ // WARN: missing default in values.
345
+ ss << "the default value '" << parameter.defaultValue << "' of parameter '"<< parameter.name <<"' is not in its list of expected values";
346
+ printWarning = true;
347
+ }
348
+
349
+ if (printWarning) {
350
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
351
+ report.warnings.push_back(Warning(ss.str(),
352
+ LogicalErrorWarning,
353
+ sourceMap));
354
+ }
355
+ }
356
+
357
+ /** Determine if a signature is a valid parameter*/
358
+ static bool isValidParameterSignature(const mdp::ByteBuffer& signature) {
359
+
360
+ mdp::ByteBuffer innerSignature = signature;
361
+ innerSignature = TrimString(innerSignature);
362
+
363
+ if (innerSignature.length() == 0) {
364
+ return false; // Empty string, invalid
365
+ }
366
+
367
+ size_t firstSpace = innerSignature.find(" ");
368
+
369
+ if (firstSpace == std::string::npos) {
370
+ return RegexMatch(innerSignature, "^" PARAMETER_IDENTIFIER "$");
371
+ }
372
+
373
+ std::string paramName = innerSignature.substr(0, firstSpace);
374
+
375
+ if (!RegexMatch(paramName, "^" PARAMETER_IDENTIFIER "$")) {
376
+ return false; // Invalid param name
377
+ }
378
+
379
+ // Remove param name
380
+ innerSignature = innerSignature.substr(firstSpace + 1);
381
+ size_t descriptionPos = innerSignature.find(snowcrash::DescriptionIdentifier);
382
+
383
+ // Remove description
384
+ if (descriptionPos != std::string::npos) {
385
+ innerSignature = innerSignature.substr(0, descriptionPos);
386
+ innerSignature = TrimString(innerSignature);
387
+ }
388
+
389
+ size_t attributesPos = innerSignature.find("(");
390
+
391
+ if (attributesPos != std::string::npos) {
392
+ size_t endOfAttributesPos = innerSignature.find_last_of(")");
393
+
394
+ if (endOfAttributesPos == std::string::npos) {
395
+ return false; // Expecting close of attributes
396
+ }
397
+
398
+ // Remove attributes
399
+ innerSignature = innerSignature.substr(0, attributesPos);
400
+ innerSignature = TrimString(innerSignature);
401
+ }
402
+
403
+ if (innerSignature.length() == 0) {
404
+ return true;
405
+ }
406
+
407
+ if (innerSignature.substr(0,1) == "=") {
408
+ innerSignature = innerSignature.substr(1);
409
+ innerSignature = TrimString(innerSignature);
410
+
411
+ if (innerSignature.length() == 0) {
412
+ return false; // No default value
413
+ }
414
+
415
+ if (innerSignature.substr(0,1) == "`" && innerSignature.substr(innerSignature.length()-1,1) == "`") {
416
+ return true;
417
+ }
418
+ }
419
+
420
+ return false;
421
+ }
422
+
423
+ };
424
+
425
+ /** Parameter Section Parser */
426
+ typedef SectionParser<Parameter, ListSectionAdapter> ParameterParser;
427
+ }
428
+
429
+ #endif