1#include "parseRawGrammar.h"
2#include "rapidjson/document.h"
3#include "rapidjson/error/en.h"
6using namespace rapidjson;
11static std::string* getStringPtr(
const Value& val) {
13 return new std::string(val.GetString(), val.GetStringLength());
19static IRawRule* parseRule(
const Value& ruleObj);
20static std::vector<IRawRule*>* parsePatterns(
const Value& patternsArray);
23static IRawCaptures* parseCaptures(
const Value& capturesObj) {
24 if (!capturesObj.IsObject()) {
28 IRawCaptures* captures =
new IRawCaptures();
29 for (
auto it = capturesObj.MemberBegin(); it != capturesObj.MemberEnd(); ++it) {
30 std::string key(it->name.GetString(), it->name.GetStringLength());
31 IRawRule* rule =
new IRawRule();
33 if (it->value.IsObject()) {
34 const Value& ruleObj = it->value;
36 if (ruleObj.HasMember(
"name") && ruleObj[
"name"].IsString()) {
37 rule->name = getStringPtr(ruleObj[
"name"]);
39 if (ruleObj.HasMember(
"contentName") && ruleObj[
"contentName"].IsString()) {
40 rule->contentName = getStringPtr(ruleObj[
"contentName"]);
42 if (ruleObj.HasMember(
"patterns") && ruleObj[
"patterns"].IsArray()) {
44 rule->patterns = parsePatterns(ruleObj[
"patterns"]);
48 captures->captures[key] = rule;
55static std::vector<IRawRule*>* parsePatterns(
const Value& patternsArray) {
56 if (!patternsArray.IsArray()) {
60 std::vector<IRawRule*>* patterns =
new std::vector<IRawRule*>();
61 for (SizeType i = 0; i < patternsArray.Size(); i++) {
62 const Value& patternObj = patternsArray[i];
63 if (patternObj.IsObject()) {
64 patterns->push_back(parseRule(patternObj));
72static IRawRepository* parseRepository(
const Value& repoObj) {
73 if (!repoObj.IsObject()) {
77 IRawRepository* repository =
new IRawRepository();
79 for (
auto it = repoObj.MemberBegin(); it != repoObj.MemberEnd(); ++it) {
80 std::string key(it->name.GetString(), it->name.GetStringLength());
83 if (it->value.IsObject()) {
84 repository->selfRule = parseRule(it->value);
86 }
else if (key ==
"$base") {
87 if (it->value.IsObject()) {
88 repository->baseRule = parseRule(it->value);
91 if (it->value.IsObject()) {
92 repository->rules[key] = parseRule(it->value);
101static IRawRule* parseRule(
const Value& ruleObj) {
102 if (!ruleObj.IsObject()) {
106 IRawRule* rule =
new IRawRule();
109 if (ruleObj.HasMember(
"include") && ruleObj[
"include"].IsString()) {
110 rule->include = getStringPtr(ruleObj[
"include"]);
114 if (ruleObj.HasMember(
"name") && ruleObj[
"name"].IsString()) {
115 rule->name = getStringPtr(ruleObj[
"name"]);
119 if (ruleObj.HasMember(
"contentName") && ruleObj[
"contentName"].IsString()) {
120 rule->contentName = getStringPtr(ruleObj[
"contentName"]);
124 if (ruleObj.HasMember(
"match") && ruleObj[
"match"].IsString()) {
125 rule->match = getStringPtr(ruleObj[
"match"]);
129 if (ruleObj.HasMember(
"captures") && ruleObj[
"captures"].IsObject()) {
130 rule->captures = parseCaptures(ruleObj[
"captures"]);
134 if (ruleObj.HasMember(
"begin") && ruleObj[
"begin"].IsString()) {
135 rule->begin = getStringPtr(ruleObj[
"begin"]);
139 if (ruleObj.HasMember(
"beginCaptures") && ruleObj[
"beginCaptures"].IsObject()) {
140 rule->beginCaptures = parseCaptures(ruleObj[
"beginCaptures"]);
144 if (ruleObj.HasMember(
"end") && ruleObj[
"end"].IsString()) {
145 rule->end = getStringPtr(ruleObj[
"end"]);
149 if (ruleObj.HasMember(
"endCaptures") && ruleObj[
"endCaptures"].IsObject()) {
150 rule->endCaptures = parseCaptures(ruleObj[
"endCaptures"]);
154 if (ruleObj.HasMember(
"while") && ruleObj[
"while"].IsString()) {
155 rule->whilePattern = getStringPtr(ruleObj[
"while"]);
159 if (ruleObj.HasMember(
"whileCaptures") && ruleObj[
"whileCaptures"].IsObject()) {
160 rule->whileCaptures = parseCaptures(ruleObj[
"whileCaptures"]);
164 if (ruleObj.HasMember(
"patterns") && ruleObj[
"patterns"].IsArray()) {
165 rule->patterns = parsePatterns(ruleObj[
"patterns"]);
169 if (ruleObj.HasMember(
"repository") && ruleObj[
"repository"].IsObject()) {
170 rule->repository = parseRepository(ruleObj[
"repository"]);
174 if (ruleObj.HasMember(
"applyEndPatternLast") && ruleObj[
"applyEndPatternLast"].IsBool()) {
175 rule->applyEndPatternLast =
new bool(ruleObj[
"applyEndPatternLast"].GetBool());
182IRawGrammar* parseJSONGrammar(
const std::string& content,
const std::string* filename) {
186 ParseResult result = doc.Parse(content.c_str());
188 std::string error =
"JSON parse error: ";
189 error += GetParseError_En(result.Code());
190 error +=
" at offset " + std::to_string(result.Offset());
191 throw std::runtime_error(error);
194 if (!doc.IsObject()) {
195 throw std::runtime_error(
"Grammar JSON must be an object");
198 IRawGrammar* grammar =
new IRawGrammar();
201 if (doc.HasMember(
"scopeName") && doc[
"scopeName"].IsString()) {
202 grammar->scopeName = std::string(doc[
"scopeName"].GetString(),
203 doc[
"scopeName"].GetStringLength());
206 throw std::runtime_error(
"Grammar must have a scopeName");
210 if (doc.HasMember(
"patterns") && doc[
"patterns"].IsArray()) {
211 const Value& patternsArray = doc[
"patterns"];
213 grammar->patterns =
new std::vector<IRawRule*>();
214 for (SizeType i = 0; i < patternsArray.Size(); i++) {
215 if (patternsArray[i].IsObject()) {
216 grammar->patterns->push_back(parseRule(patternsArray[i]));
222 if (doc.HasMember(
"repository") && doc[
"repository"].IsObject()) {
223 grammar->repository = parseRepository(doc[
"repository"]);
227 if (doc.HasMember(
"injections") && doc[
"injections"].IsObject()) {
228 grammar->injections =
new std::map<std::string, IRawRule*>();
229 const Value& injectionsObj = doc[
"injections"];
231 for (
auto it = injectionsObj.MemberBegin(); it != injectionsObj.MemberEnd(); ++it) {
232 std::string key(it->name.GetString(), it->name.GetStringLength());
233 if (it->value.IsObject()) {
234 (*grammar->injections)[key] = parseRule(it->value);
240 if (doc.HasMember(
"injectionSelector") && doc[
"injectionSelector"].IsString()) {
241 grammar->injectionSelector = getStringPtr(doc[
"injectionSelector"]);
245 if (doc.HasMember(
"fileTypes") && doc[
"fileTypes"].IsArray()) {
246 grammar->fileTypes =
new std::vector<std::string>();
247 const Value& fileTypesArray = doc[
"fileTypes"];
248 for (SizeType i = 0; i < fileTypesArray.Size(); i++) {
249 if (fileTypesArray[i].IsString()) {
250 grammar->fileTypes->push_back(
251 std::string(fileTypesArray[i].GetString(),
252 fileTypesArray[i].GetStringLength())
259 if (doc.HasMember(
"name") && doc[
"name"].IsString()) {
260 grammar->name = getStringPtr(doc[
"name"]);
264 if (doc.HasMember(
"firstLineMatch") && doc[
"firstLineMatch"].IsString()) {
265 grammar->firstLineMatch = getStringPtr(doc[
"firstLineMatch"]);
272IRawGrammar* parseRawGrammar(
const std::string& content,
const std::string* filePath) {
277 if (filePath !=
nullptr) {
279 size_t dotPos = filePath->find_last_of(
'.');
280 if (dotPos != std::string::npos) {
281 std::string ext = filePath->substr(dotPos);
282 isJSON = (ext ==
".json");
287 return parseJSONGrammar(content, filePath);
289 throw std::runtime_error(
"Only JSON grammar format is currently supported");