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