Skip to content

Commit aa23ad0

Browse files
committed
'Characger range out of order' problem support
1 parent 16685ba commit aa23ad0

File tree

2 files changed

+49
-17
lines changed

2 files changed

+49
-17
lines changed

peglib.h

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ inline std::string resolve_escape_sequence(const char *s, size_t n) {
287287
auto ch = s[i];
288288
if (ch == '\\') {
289289
i++;
290-
if (i == n) { throw std::runtime_error("Invalid escape sequence..."); }
290+
assert(i < n);
291+
291292
switch (s[i]) {
292293
case 'f':
293294
r += '\f';
@@ -3369,6 +3370,17 @@ class ParserGenerator {
33693370
Data() : grammar(std::make_shared<Grammar>()) {}
33703371
};
33713372

3373+
class SyntaxErrorException : public std::runtime_error {
3374+
public:
3375+
SyntaxErrorException(const char *what_arg, std::pair<size_t, size_t> r)
3376+
: std::runtime_error(what_arg), r_(r) {}
3377+
3378+
std::pair<size_t, size_t> line_info() const { return r_; }
3379+
3380+
private:
3381+
std::pair<size_t, size_t> r_;
3382+
};
3383+
33723384
void make_grammar() {
33733385
// Setup PEG syntax parser
33743386
g["Grammar"] <= seq(g["Spacing"], oom(g["Definition"]), g["EndOfFile"]);
@@ -3822,6 +3834,10 @@ class ParserGenerator {
38223834
auto s2 = std::any_cast<std::string>(vs[1]);
38233835
auto cp1 = decode_codepoint(s1.data(), s1.length());
38243836
auto cp2 = decode_codepoint(s2.data(), s2.length());
3837+
if (cp1 > cp2) {
3838+
throw SyntaxErrorException("characer range is out of order...",
3839+
vs.line_info());
3840+
}
38253841
return std::pair(cp1, cp2);
38263842
}
38273843
case 1: {
@@ -4026,19 +4042,27 @@ class ParserGenerator {
40264042
}
40274043
}
40284044

4029-
std::any dt = &data;
4030-
auto r = g["Grammar"].parse(s, n, dt, nullptr, log);
4045+
try {
4046+
std::any dt = &data;
4047+
auto r = g["Grammar"].parse(s, n, dt, nullptr, log);
40314048

4032-
if (!r.ret) {
4033-
if (log) {
4034-
if (r.error_info.message_pos) {
4035-
auto line = line_info(s, r.error_info.message_pos);
4036-
log(line.first, line.second, r.error_info.message,
4037-
r.error_info.label);
4038-
} else {
4039-
auto line = line_info(s, r.error_info.error_pos);
4040-
log(line.first, line.second, "syntax error", r.error_info.label);
4049+
if (!r.ret) {
4050+
if (log) {
4051+
if (r.error_info.message_pos) {
4052+
auto line = line_info(s, r.error_info.message_pos);
4053+
log(line.first, line.second, r.error_info.message,
4054+
r.error_info.label);
4055+
} else {
4056+
auto line = line_info(s, r.error_info.error_pos);
4057+
log(line.first, line.second, "syntax error", r.error_info.label);
4058+
}
40414059
}
4060+
return {};
4061+
}
4062+
} catch (const SyntaxErrorException &e) {
4063+
if (log) {
4064+
auto line = e.line_info();
4065+
log(line.first, line.second, e.what(), "");
40424066
}
40434067
return {};
40444068
}
@@ -4067,7 +4091,7 @@ class ParserGenerator {
40674091
if (log) {
40684092
auto line = line_info(s, ptr);
40694093
log(line.first, line.second,
4070-
"The definition '" + name + "' is already defined.", "");
4094+
"the definition '" + name + "' is already defined.", "");
40714095
}
40724096
}
40734097
ret = false;
@@ -4079,7 +4103,7 @@ class ParserGenerator {
40794103
if (log) {
40804104
auto line = line_info(s, ptr);
40814105
log(line.first, line.second,
4082-
"The instruction '" + type + "' is already defined.", "");
4106+
"the instruction '" + type + "' is already defined.", "");
40834107
}
40844108
}
40854109
ret = false;
@@ -4091,7 +4115,7 @@ class ParserGenerator {
40914115
if (log) {
40924116
auto line = line_info(s, ptr);
40934117
log(line.first, line.second,
4094-
"The back reference '" + name + "' is undefined.", "");
4118+
"the back reference '" + name + "' is undefined.", "");
40954119
}
40964120
}
40974121
ret = false;
@@ -4107,7 +4131,7 @@ class ParserGenerator {
41074131
if (log) {
41084132
auto line = line_info(s, s);
41094133
log(line.first, line.second,
4110-
"The specified start rule '" + requested_start +
4134+
"the specified start rule '" + requested_start +
41114135
"' is undefined.",
41124136
"");
41134137
}
@@ -4125,7 +4149,7 @@ class ParserGenerator {
41254149
if (log) {
41264150
auto line = line_info(s, start_rule.s_);
41274151
log(line.first, line.second,
4128-
"Ignore operator cannot be applied to '" + start_rule.name + "'.",
4152+
"ignore operator cannot be applied to '" + start_rule.name + "'.",
41294153
"");
41304154
}
41314155
ret = false;

test/test1.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,3 +1321,11 @@ TEST(GeneralTest, SpecifyStartRule) {
13211321
EXPECT_TRUE(peg.parse(" [one] , [two] "));
13221322
}
13231323
}
1324+
1325+
TEST(GeneralTest, InvalidRange) {
1326+
parser parser("S <- [z-a]");
1327+
1328+
bool ret = parser;
1329+
EXPECT_FALSE(ret);
1330+
}
1331+

0 commit comments

Comments
 (0)