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
|
||||
struct SemanticValues : protected std::vector<any>
|
||||
{
|
||||
// Input text
|
||||
const char* path;
|
||||
const char* ss;
|
||||
|
||||
// Matched string
|
||||
std::string str() const; // Matched string
|
||||
const char* c_str() const; // Matched string start
|
||||
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
|
||||
std::vector<
|
||||
std::pair<
|
||||
|
89
peglib.h
89
peglib.h
@ -205,19 +205,70 @@ auto make_scope_exit(EF&& exit_function) -> scope_exit<EF> {
|
||||
* 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
|
||||
*/
|
||||
struct SemanticValues : protected std::vector<any>
|
||||
{
|
||||
// Input text
|
||||
const char* path;
|
||||
const char* ss;
|
||||
|
||||
// Matched string
|
||||
const char* c_str() const { return s_; }
|
||||
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_; }
|
||||
|
||||
// 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) {}
|
||||
|
||||
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_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:
|
||||
friend class Context;
|
||||
friend class PrioritizedChoice;
|
||||
@ -1595,29 +1628,9 @@ inline std::shared_ptr<Ope> wsp(const std::shared_ptr<Ope>& ope) {
|
||||
* 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::function<void (size_t, size_t, const std::string&)> Log;
|
||||
|
||||
//typedef std::unordered_map<std::string, std::shared_ptr<Ope>> Rules;
|
||||
|
||||
class ParserGenerator
|
||||
{
|
||||
public:
|
||||
|
28
test/test.cc
28
test/test.cc
@ -825,6 +825,34 @@ TEST_CASE("Japanese character", "[unicode]")
|
||||
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) {
|
||||
auto n = strlen(s);
|
||||
auto r = g[d].parse(s, n);
|
||||
|
Loading…
Reference in New Issue
Block a user