Added line_info method on SemanticValues.

This commit is contained in:
yhirose 2017-11-03 22:27:08 -04:00
parent ebfafc3947
commit e72b630455
3 changed files with 86 additions and 38 deletions

View File

@ -104,11 +104,18 @@ Here shows the `SemanticValues` structure:
```cpp ```cpp
struct SemanticValues : protected std::vector<any> struct SemanticValues : protected std::vector<any>
{ {
// Input text
const char* path;
const char* ss;
// Matched string // Matched string
std::string str() const; // Matched string std::string str() const; // Matched string
const char* c_str() const; // Matched string start const char* c_str() const; // Matched string start
size_t length() const; // Matched string length size_t length() const; // Matched string length
// Line number and column at which the matched string is
std::pair<size_t, size_t> line_info() const;
// Tokens // Tokens
std::vector< std::vector<
std::pair< std::pair<

View File

@ -205,19 +205,70 @@ auto make_scope_exit(EF&& exit_function) -> scope_exit<EF> {
* PEG * PEG
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
/*
* Line information utility function
*/
inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
auto p = start;
auto col_ptr = p;
auto no = 1;
while (p < cur) {
if (*p == '\n') {
no++;
col_ptr = p + 1;
}
p++;
}
auto col = p - col_ptr + 1;
return std::make_pair(no, col);
}
/* /*
* Semantic values * Semantic values
*/ */
struct SemanticValues : protected std::vector<any> struct SemanticValues : protected std::vector<any>
{ {
// Input text
const char* path; const char* path;
const char* ss; const char* ss;
// Matched string
const char* c_str() const { return s_; } const char* c_str() const { return s_; }
size_t length() const { return n_; } size_t length() const { return n_; }
std::string str() const {
return std::string(s_, n_);
}
// Line number and column at which the matched string is
std::pair<size_t, size_t> line_info() const {
return peg::line_info(ss, s_);
}
// Choice number (0 based index)
size_t choice() const { return choice_; } size_t choice() const { return choice_; }
// Tokens
std::vector<std::pair<const char*, size_t>> tokens; std::vector<std::pair<const char*, size_t>> tokens;
std::string token(size_t id = 0) const {
if (!tokens.empty()) {
assert(id < tokens.size());
const auto& tok = tokens[id];
return std::string(tok.first, tok.second);
}
return std::string(s_, n_);
}
// Transform the semantic value vector to another vector
template <typename T>
auto transform(size_t beg = 0, size_t end = static_cast<size_t>(-1)) const -> vector<T> {
return this->transform(beg, end, [](const any& v) { return v.get<T>(); });
}
SemanticValues() : s_(nullptr), n_(0), choice_(0) {} SemanticValues() : s_(nullptr), n_(0), choice_(0) {}
using std::vector<any>::iterator; using std::vector<any>::iterator;
@ -243,24 +294,6 @@ struct SemanticValues : protected std::vector<any>
using std::vector<any>::emplace; using std::vector<any>::emplace;
using std::vector<any>::emplace_back; using std::vector<any>::emplace_back;
std::string str() const {
return std::string(s_, n_);
}
std::string token(size_t id = 0) const {
if (!tokens.empty()) {
assert(id < tokens.size());
const auto& tok = tokens[id];
return std::string(tok.first, tok.second);
}
return std::string(s_, n_);
}
template <typename T>
auto transform(size_t beg = 0, size_t end = static_cast<size_t>(-1)) const -> vector<T> {
return this->transform(beg, end, [](const any& v) { return v.get<T>(); });
}
private: private:
friend class Context; friend class Context;
friend class PrioritizedChoice; friend class PrioritizedChoice;
@ -1595,29 +1628,9 @@ inline std::shared_ptr<Ope> wsp(const std::shared_ptr<Ope>& ope) {
* PEG parser generator * PEG parser generator
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
auto p = start;
auto col_ptr = p;
auto no = 1;
while (p < cur) {
if (*p == '\n') {
no++;
col_ptr = p + 1;
}
p++;
}
auto col = p - col_ptr + 1;
return std::make_pair(no, col);
}
typedef std::unordered_map<std::string, Definition> Grammar; typedef std::unordered_map<std::string, Definition> Grammar;
typedef std::function<void (size_t, size_t, const std::string&)> Log; typedef std::function<void (size_t, size_t, const std::string&)> Log;
//typedef std::unordered_map<std::string, std::shared_ptr<Ope>> Rules;
class ParserGenerator class ParserGenerator
{ {
public: public:

View File

@ -825,6 +825,34 @@ TEST_CASE("Japanese character", "[unicode]")
REQUIRE(ret == true); REQUIRE(ret == true);
} }
TEST_CASE("Line information test", "[line information]")
{
parser parser(R"(
S <- _ (WORD _)+
WORD <- [A-Za-z]+
~_ <- [ \t\r\n]+
)");
std::vector<std::pair<int, int>> locations;
parser["WORD"] = [&](const peg::SemanticValues& sv) {
locations.push_back(sv.line_info());
};
bool ret = parser;
REQUIRE(ret == true);
ret = parser.parse(" Mon Tue Wed \nThu Fri Sat\nSun\n");
REQUIRE(ret == true);
REQUIRE(locations[0] == std::make_pair(1, 2));
REQUIRE(locations[1] == std::make_pair(1, 6));
REQUIRE(locations[2] == std::make_pair(1, 10));
REQUIRE(locations[3] == std::make_pair(2, 1));
REQUIRE(locations[4] == std::make_pair(2, 6));
REQUIRE(locations[5] == std::make_pair(2, 11));
REQUIRE(locations[6] == std::make_pair(3, 1));
}
bool exact(Grammar& g, const char* d, const char* s) { bool exact(Grammar& g, const char* d, const char* s) {
auto n = strlen(s); auto n = strlen(s);
auto r = g[d].parse(s, n); auto r = g[d].parse(s, n);