mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Added line_info method on SemanticValues.
This commit is contained in:
parent
ebfafc3947
commit
e72b630455
@ -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<
|
||||||
|
89
peglib.h
89
peglib.h
@ -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:
|
||||||
|
28
test/test.cc
28
test/test.cc
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user