Skip to content

Commit 57b6ddf

Browse files
author
ranga.code
committed
added code and examples.
1 parent 71a4bf7 commit 57b6ddf

File tree

5 files changed

+310
-0
lines changed

5 files changed

+310
-0
lines changed

example-code/checker.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <fstream>
2+
#include <iostream>
3+
#include "yaml.h"
4+
#include "yavl.h"
5+
6+
using namespace std;
7+
8+
int main(int argc, char **argv)
9+
{
10+
std::ifstream grin; // grammar file
11+
grin.open(argv[1]);
12+
13+
std::ifstream yin; // file to be checked
14+
yin.open(argv[2]);
15+
16+
YAML::Node gr;
17+
try {
18+
YAML::Parser parser(grin);
19+
parser.GetNextDocument(gr);
20+
} catch(const YAML::Exception& e) {
21+
std::cerr << "Error reading grammar: " << e.what() << "\n";
22+
return 1;
23+
}
24+
25+
YAML::Node doc;
26+
try {
27+
YAML::Parser parser(yin);
28+
parser.GetNextDocument(doc);
29+
} catch(const YAML::Exception& e) {
30+
std::cerr << "Error reading document: " << e.what() << "\n";
31+
return 2;
32+
}
33+
34+
YAVL yavl(gr, doc);
35+
bool ok = yavl.validate();
36+
if (!ok) {
37+
cout << "ERRORS FOUND: " << endl << endl;
38+
cout << yavl.get_errors();
39+
}
40+
return !ok;
41+
}
42+
43+

example-specs/gr3.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# spec to check y0.gr3.yaml
2+
map:
3+
HEADER:
4+
map:
5+
name: [string: ]
6+
version: [string: ]
7+
size: [enum: [big, small]]
8+
pieces:
9+
map:
10+
a:
11+
list: [string: ]
12+
b:
13+
list: [uint64: ]

example-specs/y0.gr3.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# to be checked against gr3.yaml
2+
HEADER:
3+
name: myname
4+
version: 1.02
5+
size: xbig
6+
pieces:
7+
a: [hello, world]
8+
b: [x100, 200]

src/yavl.cpp

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#include <stdio.h>
2+
#include <assert.h>
3+
#include "yaml.h"
4+
#include "yavl.h"
5+
6+
using namespace std;
7+
8+
ostream& operator << (ostream& os, const Path& path)
9+
{
10+
for (Path::const_iterator i = path.begin(); i != path.end(); ++i) {
11+
// no dot before list indexes and before first element
12+
if ((i != path.begin()) && ((*i)[0] != '[')) {
13+
os << '.';
14+
}
15+
os << *i;
16+
}
17+
return os;
18+
}
19+
20+
ostream& operator << (ostream& os, const YAVL_Exception& v)
21+
{
22+
os << "REASON: " << v.why << endl;
23+
os << " doc path: " << v.doc_path << endl;
24+
os << " treespec path: " << v.gr_path << endl;
25+
os << endl;
26+
return os;
27+
}
28+
29+
ostream& operator << (ostream& os, const Errors& v)
30+
{
31+
for (Errors::const_iterator i = v.begin(); i != v.end(); ++i) {
32+
os << *i;
33+
}
34+
return os;
35+
}
36+
37+
const string& YAVL::type2str(YAML::CONTENT_TYPE t)
38+
{
39+
static string nonestr = "none";
40+
static string scalarstr = "scalar";
41+
static string liststr = "list";
42+
static string mapstr = "map";
43+
44+
assert( (t >= YAML::CT_NONE) && (t <= YAML::CT_MAP) );
45+
46+
switch (t) {
47+
case YAML::CT_NONE:
48+
return nonestr;
49+
case YAML::CT_SCALAR:
50+
return scalarstr;
51+
case YAML::CT_SEQUENCE:
52+
return liststr;
53+
case YAML::CT_MAP:
54+
return mapstr;
55+
}
56+
assert(0);
57+
return nonestr;
58+
}
59+
60+
int YAVL::num_keys(const YAML::Node& doc)
61+
{
62+
if (doc.GetType() != YAML::CT_MAP) {
63+
return 0;
64+
}
65+
int num = 0;
66+
for (YAML::Iterator i = doc.begin(); i != doc.end(); ++i) {
67+
num++;
68+
}
69+
return num;
70+
}
71+
72+
bool YAVL::validate_map(const YAML::Node &mapNode, const YAML::Node &doc)
73+
{
74+
if (doc.GetType() != YAML::CT_MAP) {
75+
string reason = "expected map, but found " + type2str(doc.GetType());
76+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
77+
return false;
78+
}
79+
80+
bool ok = true;
81+
for (YAML::Iterator i = mapNode.begin(); i != mapNode.end(); ++i) {
82+
string key = i.first();
83+
const YAML::Node &valueNode = i.second();
84+
const YAML::Node *docMapNode = 0;
85+
if (!(docMapNode = doc.FindValue(key))) {
86+
string reason = "key: " + key + " not found.";
87+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
88+
ok = false;
89+
} else {
90+
doc_path.push_back(key);
91+
gr_path.push_back(key);
92+
93+
ok = validate_doc(valueNode, *docMapNode) && ok;
94+
95+
gr_path.pop_back();
96+
doc_path.pop_back();
97+
}
98+
}
99+
return ok;
100+
}
101+
102+
bool YAVL::validate_leaf(const YAML::Node &gr, const YAML::Node &doc)
103+
{
104+
assert( gr.GetType() == YAML::CT_SEQUENCE );
105+
106+
const YAML::Node& typespec_map = gr[0];
107+
assert( num_keys(typespec_map) == 1);
108+
109+
string type = typespec_map.begin().first();
110+
const YAML::Node& type_specifics = typespec_map.begin().second();
111+
112+
bool ok = true;
113+
if (type == "string") {
114+
try {
115+
string tmp = doc;
116+
ok = true;
117+
} catch (const YAML::InvalidScalar& e) {
118+
string reason = "unable to convert to string.";
119+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
120+
ok = false;
121+
}
122+
} else if (type == "uint64") {
123+
try {
124+
unsigned long long tmp;
125+
doc >> tmp;
126+
ok = true;
127+
} catch (const YAML::InvalidScalar& e) {
128+
string tmp = doc;
129+
string reason = "unable to convert " + tmp + " to long long.";
130+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
131+
ok = false;
132+
}
133+
} else if (type == "enum") {
134+
ok = false;
135+
string docValue = doc;
136+
for (YAML::Iterator i = type_specifics.begin(); i != type_specifics.end(); ++i) {
137+
if (*i == docValue) {
138+
ok = true;
139+
break;
140+
}
141+
}
142+
if (!ok) {
143+
string reason = "enum string " + docValue + " is not allowed.";
144+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
145+
}
146+
}
147+
return ok;
148+
}
149+
150+
bool YAVL::validate_list(const YAML::Node &gr, const YAML::Node &doc)
151+
{
152+
if (doc.GetType() != YAML::CT_SEQUENCE) {
153+
string reason = "expected list, but found " + type2str(doc.GetType());
154+
gen_error(YAVL_Exception(reason, gr_path, doc_path));
155+
return false;
156+
}
157+
158+
bool ok = true;
159+
int n = 0;
160+
char buf[128];
161+
162+
for (YAML::Iterator i = doc.begin(); i != doc.end(); ++i, ++n) {
163+
snprintf(buf, sizeof(buf), "[%d]", n);
164+
doc_path.push_back(buf);
165+
ok = validate_doc(gr, *i) && ok;
166+
doc_path.pop_back();
167+
}
168+
return ok;
169+
}
170+
171+
bool YAVL::validate_doc(const YAML::Node &gr, const YAML::Node &doc)
172+
{
173+
bool ok = true;
174+
const YAML::Node *mapNode = 0;
175+
const YAML::Node *listNode = 0;
176+
if ((mapNode = gr.FindValue("map"))) {
177+
gr_path.push_back("map");
178+
ok = validate_map(*mapNode, doc) && ok;
179+
gr_path.pop_back();
180+
} else if ((listNode = gr.FindValue("list"))) {
181+
gr_path.push_back("list");
182+
ok = validate_list(*listNode, doc) && ok;
183+
gr_path.pop_back();
184+
} else {
185+
ok = validate_leaf(gr, doc) && ok;
186+
}
187+
return ok;
188+
}

src/yavl.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#ifndef YAVL_H_
2+
#define YAVL_H_
3+
4+
#include "yaml.h"
5+
#include <vector>
6+
#include <string>
7+
#include <ostream>
8+
9+
typedef std::vector<std::string> Path;
10+
11+
class YAVL_Exception {
12+
public:
13+
std::string why;
14+
Path gr_path;
15+
Path doc_path;
16+
YAVL_Exception(const std::string _why,
17+
const Path& _gr_path,
18+
const Path& _doc_path) :
19+
why(_why), gr_path(_gr_path), doc_path(_doc_path) {};
20+
};
21+
22+
typedef std::vector<YAVL_Exception> Errors;
23+
24+
class YAVL {
25+
const YAML::Node& gr;
26+
const YAML::Node& doc;
27+
Path gr_path;
28+
Path doc_path;
29+
Errors errors;
30+
31+
int num_keys(const YAML::Node& doc);
32+
const std::string& type2str(YAML::CONTENT_TYPE t);
33+
bool validate_map(const YAML::Node &mapNode, const YAML::Node &doc);
34+
bool validate_leaf(const YAML::Node &gr, const YAML::Node &doc);
35+
bool validate_list(const YAML::Node &gr, const YAML::Node &doc);
36+
bool validate_doc(const YAML::Node &gr, const YAML::Node &doc);
37+
38+
void gen_error(const YAVL_Exception& err) {
39+
errors.push_back(err);
40+
}
41+
42+
public:
43+
YAVL(const YAML::Node& _gr, const YAML::Node& _doc) :
44+
gr(_gr), doc(_doc) {};
45+
bool validate() {
46+
return validate_doc(gr, doc);
47+
}
48+
const Errors& get_errors() {
49+
return errors;
50+
}
51+
};
52+
53+
std::ostream& operator << (std::ostream& os, const Path& path);
54+
std::ostream& operator << (std::ostream& os, const YAVL_Exception& v);
55+
std::ostream& operator << (std::ostream& os, const Errors& v);
56+
57+
#endif
58+

0 commit comments

Comments
 (0)