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
@@ -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