Skip to content

Commit e72b630

Browse files
committed
Added line_info method on SemanticValues.
1 parent ebfafc3 commit e72b630

File tree

3 files changed

+86
-38
lines changed

3 files changed

+86
-38
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,18 @@ Here shows the `SemanticValues` structure:
104104
```cpp
105105
struct SemanticValues : protected std::vector<any>
106106
{
107+
// Input text
108+
const char* path;
109+
const char* ss;
110+
107111
// Matched string
108112
std::string str() const; // Matched string
109113
const char* c_str() const; // Matched string start
110114
size_t length() const; // Matched string length
111115

116+
// Line number and column at which the matched string is
117+
std::pair<size_t, size_t> line_info() const;
118+
112119
// Tokens
113120
std::vector<
114121
std::pair<

peglib.h

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -205,19 +205,70 @@ auto make_scope_exit(EF&& exit_function) -> scope_exit<EF> {
205205
* PEG
206206
*---------------------------------------------------------------------------*/
207207

208+
/*
209+
* Line information utility function
210+
*/
211+
inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
212+
auto p = start;
213+
auto col_ptr = p;
214+
auto no = 1;
215+
216+
while (p < cur) {
217+
if (*p == '\n') {
218+
no++;
219+
col_ptr = p + 1;
220+
}
221+
p++;
222+
}
223+
224+
auto col = p - col_ptr + 1;
225+
226+
return std::make_pair(no, col);
227+
}
228+
208229
/*
209230
* Semantic values
210231
*/
211232
struct SemanticValues : protected std::vector<any>
212233
{
234+
// Input text
213235
const char* path;
214236
const char* ss;
237+
238+
// Matched string
215239
const char* c_str() const { return s_; }
216240
size_t length() const { return n_; }
241+
242+
std::string str() const {
243+
return std::string(s_, n_);
244+
}
245+
246+
// Line number and column at which the matched string is
247+
std::pair<size_t, size_t> line_info() const {
248+
return peg::line_info(ss, s_);
249+
}
250+
251+
// Choice number (0 based index)
217252
size_t choice() const { return choice_; }
218253

254+
// Tokens
219255
std::vector<std::pair<const char*, size_t>> tokens;
220256

257+
std::string token(size_t id = 0) const {
258+
if (!tokens.empty()) {
259+
assert(id < tokens.size());
260+
const auto& tok = tokens[id];
261+
return std::string(tok.first, tok.second);
262+
}
263+
return std::string(s_, n_);
264+
}
265+
266+
// Transform the semantic value vector to another vector
267+
template <typename T>
268+
auto transform(size_t beg = 0, size_t end = static_cast<size_t>(-1)) const -> vector<T> {
269+
return this->transform(beg, end, [](const any& v) { return v.get<T>(); });
270+
}
271+
221272
SemanticValues() : s_(nullptr), n_(0), choice_(0) {}
222273

223274
using std::vector<any>::iterator;
@@ -243,24 +294,6 @@ struct SemanticValues : protected std::vector<any>
243294
using std::vector<any>::emplace;
244295
using std::vector<any>::emplace_back;
245296

246-
std::string str() const {
247-
return std::string(s_, n_);
248-
}
249-
250-
std::string token(size_t id = 0) const {
251-
if (!tokens.empty()) {
252-
assert(id < tokens.size());
253-
const auto& tok = tokens[id];
254-
return std::string(tok.first, tok.second);
255-
}
256-
return std::string(s_, n_);
257-
}
258-
259-
template <typename T>
260-
auto transform(size_t beg = 0, size_t end = static_cast<size_t>(-1)) const -> vector<T> {
261-
return this->transform(beg, end, [](const any& v) { return v.get<T>(); });
262-
}
263-
264297
private:
265298
friend class Context;
266299
friend class PrioritizedChoice;
@@ -1595,29 +1628,9 @@ inline std::shared_ptr<Ope> wsp(const std::shared_ptr<Ope>& ope) {
15951628
* PEG parser generator
15961629
*---------------------------------------------------------------------------*/
15971630

1598-
inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
1599-
auto p = start;
1600-
auto col_ptr = p;
1601-
auto no = 1;
1602-
1603-
while (p < cur) {
1604-
if (*p == '\n') {
1605-
no++;
1606-
col_ptr = p + 1;
1607-
}
1608-
p++;
1609-
}
1610-
1611-
auto col = p - col_ptr + 1;
1612-
1613-
return std::make_pair(no, col);
1614-
}
1615-
16161631
typedef std::unordered_map<std::string, Definition> Grammar;
16171632
typedef std::function<void (size_t, size_t, const std::string&)> Log;
16181633

1619-
//typedef std::unordered_map<std::string, std::shared_ptr<Ope>> Rules;
1620-
16211634
class ParserGenerator
16221635
{
16231636
public:

test/test.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,34 @@ TEST_CASE("Japanese character", "[unicode]")
825825
REQUIRE(ret == true);
826826
}
827827

828+
TEST_CASE("Line information test", "[line information]")
829+
{
830+
parser parser(R"(
831+
S <- _ (WORD _)+
832+
WORD <- [A-Za-z]+
833+
~_ <- [ \t\r\n]+
834+
)");
835+
836+
std::vector<std::pair<int, int>> locations;
837+
parser["WORD"] = [&](const peg::SemanticValues& sv) {
838+
locations.push_back(sv.line_info());
839+
};
840+
841+
bool ret = parser;
842+
REQUIRE(ret == true);
843+
844+
ret = parser.parse(" Mon Tue Wed \nThu Fri Sat\nSun\n");
845+
REQUIRE(ret == true);
846+
847+
REQUIRE(locations[0] == std::make_pair(1, 2));
848+
REQUIRE(locations[1] == std::make_pair(1, 6));
849+
REQUIRE(locations[2] == std::make_pair(1, 10));
850+
REQUIRE(locations[3] == std::make_pair(2, 1));
851+
REQUIRE(locations[4] == std::make_pair(2, 6));
852+
REQUIRE(locations[5] == std::make_pair(2, 11));
853+
REQUIRE(locations[6] == std::make_pair(3, 1));
854+
}
855+
828856
bool exact(Grammar& g, const char* d, const char* s) {
829857
auto n = strlen(s);
830858
auto r = g[d].parse(s, n);

0 commit comments

Comments
 (0)