mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Added command-line debugger support.
This commit is contained in:
parent
24b3da5d0f
commit
5d6755ff64
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
include_directories(.)
|
||||
add_definitions("-std=c++1y")
|
||||
add_definitions("-std=c++1y" -DPEGLIB_HAS_CONSTEXPR_SUPPORT)
|
||||
|
||||
add_executable(peglint lint/peglint.cc)
|
||||
target_link_libraries(peglint pthread)
|
||||
@ -20,5 +20,5 @@ target_link_libraries(calc2 pthread)
|
||||
add_executable(calc3 example/calc3.cc)
|
||||
target_link_libraries(calc3 pthread)
|
||||
|
||||
add_executable(culebra language/main.cc language/repl.cc language/interpreter.cc language/parser.cc)
|
||||
add_executable(culebra language/main.cc)
|
||||
target_link_libraries(culebra pthread)
|
||||
|
@ -8,7 +8,11 @@ namespace culebra {
|
||||
const auto grammar_ = R"(
|
||||
|
||||
PROGRAM <- _ STATEMENTS
|
||||
STATEMENTS <- (EXPRESSION (';' _)?)*
|
||||
STATEMENTS <- (STATEMENT (';' _)?)*
|
||||
STATEMENT <- DEBUGGER / EXPRESSION
|
||||
|
||||
DEBUGGER <- 'debugger' _
|
||||
|
||||
EXPRESSION <- ASSIGNMENT / LOGICAL_OR
|
||||
|
||||
ASSIGNMENT <- MUTABLE PRIMARY (ARGUMENTS / INDEX / DOT)* '=' _ EXPRESSION
|
||||
@ -336,7 +340,10 @@ inline std::ostream& operator<<(std::ostream& os, const Value& val)
|
||||
|
||||
struct Environment
|
||||
{
|
||||
Environment() = default;
|
||||
Environment(std::shared_ptr<Environment> parent = nullptr)
|
||||
: parent(parent)
|
||||
, level(parent ? parent->level + 1 : 0) {
|
||||
}
|
||||
|
||||
void append_outer(std::shared_ptr<Environment> outer) {
|
||||
if (this->outer) {
|
||||
@ -385,12 +392,17 @@ struct Environment
|
||||
dic_[s] = Symbol{ val, mut };
|
||||
}
|
||||
|
||||
std::shared_ptr<Environment> outer;
|
||||
std::shared_ptr<Environment> outer;
|
||||
|
||||
std::shared_ptr<Environment> parent;
|
||||
size_t level;
|
||||
|
||||
private:
|
||||
std::map<std::string, Symbol> dic_;
|
||||
};
|
||||
|
||||
typedef std::function<void (const peglib::Ast& ast, std::shared_ptr<Environment> env, bool force_to_break)> Debugger;
|
||||
|
||||
inline bool ObjectValue::has(const std::string& name) const {
|
||||
if (properties->find(name) == properties->end()) {
|
||||
const auto& props = const_cast<ObjectValue*>(this)->builtins();
|
||||
@ -521,9 +533,20 @@ inline void setup_built_in_functions(Environment& env) {
|
||||
|
||||
struct Eval
|
||||
{
|
||||
static Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Eval(Debugger debugger = nullptr)
|
||||
: debugger_(debugger) {
|
||||
}
|
||||
|
||||
Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
using peglib::operator"" _;
|
||||
|
||||
if (debugger_) {
|
||||
if (ast.original_tag == "STATEMENT"_) {
|
||||
auto force_to_break = ast.tag == "DEBUGGER"_;
|
||||
debugger_(ast, env, force_to_break);
|
||||
}
|
||||
}
|
||||
|
||||
switch (ast.tag) {
|
||||
case "STATEMENTS"_: return eval_statements(ast, env);
|
||||
case "WHILE"_: return eval_while(ast, env);
|
||||
@ -547,6 +570,7 @@ struct Eval
|
||||
case "BOOLEAN"_: return eval_bool(ast, env);
|
||||
case "NUMBER"_: return eval_number(ast, env);
|
||||
case "INTERPOLATED_STRING"_: return eval_interpolated_string(ast, env);
|
||||
case "DEBUGGER"_: return Value();
|
||||
}
|
||||
|
||||
if (ast.is_token) {
|
||||
@ -558,7 +582,7 @@ struct Eval
|
||||
}
|
||||
|
||||
private:
|
||||
static Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
if (ast.is_token) {
|
||||
return eval(ast, env);
|
||||
} else if (ast.nodes.empty()) {
|
||||
@ -572,7 +596,7 @@ private:
|
||||
return eval(**it, env);
|
||||
}
|
||||
|
||||
static Value eval_while(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_while(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
for (;;) {
|
||||
auto cond = eval(*ast.nodes[0], env);
|
||||
if (!cond.to_bool()) {
|
||||
@ -583,7 +607,7 @@ private:
|
||||
return Value();
|
||||
}
|
||||
|
||||
static Value eval_if(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_if(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
const auto& nodes = ast.nodes;
|
||||
|
||||
for (auto i = 0u; i < nodes.size(); i += 2) {
|
||||
@ -600,7 +624,7 @@ private:
|
||||
return Value();
|
||||
}
|
||||
|
||||
static Value eval_function(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_function(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
std::vector<FunctionValue::Parameter> params;
|
||||
for (auto node: ast.nodes[0]->nodes) {
|
||||
auto mut = node->nodes[0]->token == "mut";
|
||||
@ -619,13 +643,13 @@ private:
|
||||
));
|
||||
};
|
||||
|
||||
static Value eval_function_call(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
Value eval_function_call(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
const auto& f = val.to_function();
|
||||
const auto& params = *f.params;
|
||||
const auto& args = ast.nodes;
|
||||
|
||||
if (params.size() <= args.size()) {
|
||||
auto callEnv = std::make_shared<Environment>();
|
||||
auto callEnv = std::make_shared<Environment>(env);
|
||||
callEnv->initialize("self", val, false);
|
||||
for (auto iprm = 0u; iprm < params.size(); iprm++) {
|
||||
auto param = params[iprm];
|
||||
@ -642,7 +666,7 @@ private:
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
static Value eval_array_reference(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
Value eval_array_reference(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
const auto& arr = val.to_array();
|
||||
auto idx = eval(ast, env).to_long();
|
||||
if (0 <= idx && idx < static_cast<long>(arr.values->size())) {
|
||||
@ -653,7 +677,7 @@ private:
|
||||
return val;
|
||||
}
|
||||
|
||||
static Value eval_property(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
Value eval_property(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||
const auto& obj = val.to_object();
|
||||
auto name = ast.token;
|
||||
if (!obj.has(name)) {
|
||||
@ -673,7 +697,7 @@ private:
|
||||
return prop;
|
||||
}
|
||||
|
||||
static Value eval_call(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_call(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
using peglib::operator"" _;
|
||||
|
||||
Value val = eval(*ast.nodes[0], env);
|
||||
@ -692,11 +716,11 @@ private:
|
||||
return std::move(val);
|
||||
}
|
||||
|
||||
static Value eval_block(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_block(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
return Value();
|
||||
}
|
||||
|
||||
static Value eval_logical_or(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_logical_or(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
assert(ast.nodes.size() > 1); // if the size is 1, thes node will be hoisted.
|
||||
Value val;
|
||||
for (auto node: ast.nodes) {
|
||||
@ -708,7 +732,7 @@ private:
|
||||
return std::move(val);
|
||||
}
|
||||
|
||||
static Value eval_logical_and(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_logical_and(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value val;
|
||||
for (auto node: ast.nodes) {
|
||||
val = eval(*node, env);
|
||||
@ -719,7 +743,7 @@ private:
|
||||
return std::move(val);
|
||||
}
|
||||
|
||||
static Value eval_condition(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_condition(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
assert(ast.nodes.size() == 3); // if the size is 1, thes node will be hoisted.
|
||||
|
||||
auto lhs = eval(*ast.nodes[0], env);
|
||||
@ -735,22 +759,22 @@ private:
|
||||
else { throw std::logic_error("invalid internal condition."); }
|
||||
}
|
||||
|
||||
static Value eval_unary_plus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_unary_plus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
|
||||
return eval(*ast.nodes[1], env);
|
||||
}
|
||||
|
||||
static Value eval_unary_minus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_unary_minus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
|
||||
return Value(eval(*ast.nodes[1], env).to_long() * -1);
|
||||
}
|
||||
|
||||
static Value eval_unary_not(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_unary_not(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
|
||||
return Value(!eval(*ast.nodes[1], env).to_bool());
|
||||
}
|
||||
|
||||
static Value eval_bin_expression(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_bin_expression(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
auto ret = eval(*ast.nodes[0], env).to_long();
|
||||
for (auto i = 1u; i < ast.nodes.size(); i += 2) {
|
||||
auto val = eval(*ast.nodes[i + 1], env).to_long();
|
||||
@ -766,7 +790,7 @@ private:
|
||||
return Value(ret);
|
||||
}
|
||||
|
||||
static Value eval_assignment(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_assignment(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
auto end = ast.nodes.size() - 1;
|
||||
|
||||
auto mut = ast.nodes[0]->token == "mut";
|
||||
@ -826,11 +850,11 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
static Value eval_identifier(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_identifier(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
return env->get(ast.token);
|
||||
};
|
||||
|
||||
static Value eval_object(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_object(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
ObjectValue obj;
|
||||
for (auto i = 0u; i < ast.nodes.size(); i++) {
|
||||
const auto& prop = *ast.nodes[i];
|
||||
@ -842,7 +866,7 @@ private:
|
||||
return Value(std::move(obj));
|
||||
}
|
||||
|
||||
static Value eval_array(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_array(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
ArrayValue arr;
|
||||
for (auto i = 0u; i < ast.nodes.size(); i++) {
|
||||
auto expr = ast.nodes[i];
|
||||
@ -852,19 +876,19 @@ private:
|
||||
return Value(std::move(arr));
|
||||
}
|
||||
|
||||
static Value eval_undefined(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_undefined(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
return Value();
|
||||
};
|
||||
|
||||
static Value eval_bool(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_bool(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
return Value(ast.token == "true");
|
||||
};
|
||||
|
||||
static Value eval_number(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_number(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
return Value(stol(ast.token));
|
||||
};
|
||||
|
||||
static Value eval_interpolated_string(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
Value eval_interpolated_string(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||
std::string s;
|
||||
for (auto node: ast.nodes) {
|
||||
const auto& val = eval(*node, env);
|
||||
@ -876,16 +900,19 @@ private:
|
||||
}
|
||||
return Value(std::move(s));
|
||||
};
|
||||
|
||||
Debugger debugger_;
|
||||
};
|
||||
|
||||
inline bool run(
|
||||
const std::string& path,
|
||||
std::shared_ptr<Environment> env,
|
||||
const char* expr,
|
||||
size_t len,
|
||||
Value& val,
|
||||
std::string& msg,
|
||||
bool print_ast)
|
||||
const std::string& path,
|
||||
std::shared_ptr<Environment> env,
|
||||
const char* expr,
|
||||
size_t len,
|
||||
Value& val,
|
||||
std::vector<std::string>& msgs,
|
||||
std::shared_ptr<peglib::Ast>& ast,
|
||||
Debugger debugger = nullptr)
|
||||
{
|
||||
try {
|
||||
auto& parser = get_parser();
|
||||
@ -893,21 +920,15 @@ inline bool run(
|
||||
parser.log = [&](size_t ln, size_t col, const std::string& err_msg) {
|
||||
std::stringstream ss;
|
||||
ss << path << ":" << ln << ":" << col << ": " << err_msg << std::endl;
|
||||
msg = ss.str();
|
||||
msgs.push_back(ss.str());
|
||||
};
|
||||
|
||||
std::shared_ptr<peglib::Ast> ast;
|
||||
|
||||
if (parser.parse_n(expr, len, ast)) {
|
||||
if (print_ast) {
|
||||
ast->print();
|
||||
}
|
||||
|
||||
val = Eval::eval(*ast, env);
|
||||
if (parser.parse_n(expr, len, ast, path.c_str())) {
|
||||
val = Eval(debugger).eval(*ast, env);
|
||||
return true;
|
||||
}
|
||||
} catch (std::runtime_error& e) {
|
||||
msg = e.what();
|
||||
msgs.push_back(e.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -24,6 +24,49 @@ bool read_file(const char* path, vector<char>& buff)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct CommandLineDebugger
|
||||
{
|
||||
void operator()(const peglib::Ast& ast, std::shared_ptr<Environment> env, bool force_to_break) {
|
||||
if (quit) {
|
||||
force_to_break = false;
|
||||
} if (line == "n" && env->level <= level) {
|
||||
force_to_break = true;
|
||||
} else if (line == "s") {
|
||||
force_to_break = true;
|
||||
} else if (line == "o" && env->level < level) {
|
||||
force_to_break = true;
|
||||
}
|
||||
|
||||
if (force_to_break) {
|
||||
for (;;) {
|
||||
line = linenoise::Readline("debug> ");
|
||||
|
||||
if (line == "bt") {
|
||||
std::cout << "level: " << env->level << std::endl;
|
||||
} else if (line == "l") { // show source file
|
||||
std::cout << "line: " << ast.line << " in " << ast.path << std::endl;
|
||||
} else if (line == "c") { // continue
|
||||
break;
|
||||
} else if (line == "n") { // step over
|
||||
break;
|
||||
} else if (line == "s") { // step into
|
||||
break;
|
||||
} else if (line == "o") { // step out
|
||||
break;
|
||||
} else if (line == "q") { // quit
|
||||
quit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
level = env->level;;
|
||||
}
|
||||
}
|
||||
|
||||
std::string line;
|
||||
size_t level = 0;
|
||||
bool quit = false;
|
||||
};
|
||||
|
||||
int repl(shared_ptr<Environment> env, bool print_ast)
|
||||
{
|
||||
for (;;) {
|
||||
@ -35,12 +78,19 @@ int repl(shared_ptr<Environment> env, bool print_ast)
|
||||
|
||||
if (!line.empty()) {
|
||||
Value val;
|
||||
string msg;
|
||||
if (run("(repl)", env, line.c_str(), line.size(), val, msg, print_ast)) {
|
||||
vector<string> msgs;
|
||||
std::shared_ptr<peglib::Ast> ast;
|
||||
auto ret = run("(repl)", env, line.c_str(), line.size(), val, msgs, ast);
|
||||
if (ret) {
|
||||
if (print_ast) {
|
||||
ast->print();
|
||||
}
|
||||
cout << val << endl;
|
||||
linenoise::AddHistory(line.c_str());
|
||||
} else if (!msg.empty()) {
|
||||
cout << msg << endl;;
|
||||
} else if (!msgs.empty()) {
|
||||
for (const auto& msg: msgs) {
|
||||
cout << msg << endl;;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,6 +102,7 @@ int main(int argc, const char** argv)
|
||||
{
|
||||
auto print_ast = false;
|
||||
auto shell = false;
|
||||
auto debug = false;
|
||||
vector<const char*> path_list;
|
||||
|
||||
int argi = 1;
|
||||
@ -61,6 +112,8 @@ int main(int argc, const char** argv)
|
||||
shell = true;
|
||||
} else if (string("--ast") == arg) {
|
||||
print_ast = true;
|
||||
} else if (string("--debug") == arg) {
|
||||
debug = true;
|
||||
} else {
|
||||
path_list.push_back(arg);
|
||||
}
|
||||
@ -81,11 +134,25 @@ int main(int argc, const char** argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
Value val;
|
||||
string msg;
|
||||
if (!run(path, env, buff.data(), buff.size(), val, msg, print_ast)) {
|
||||
cerr << msg << endl;
|
||||
Value val;
|
||||
vector<string> msgs;
|
||||
std::shared_ptr<peglib::Ast> ast;
|
||||
Debugger dbg;
|
||||
|
||||
CommandLineDebugger debugger;
|
||||
if (debug) {
|
||||
dbg = debugger;
|
||||
}
|
||||
|
||||
auto ret = run(path, env, buff.data(), buff.size(), val, msgs, ast, dbg);
|
||||
|
||||
if (!ret) {
|
||||
for (const auto& msg: msgs) {
|
||||
cerr << msg << endl;
|
||||
}
|
||||
return -1;
|
||||
} else if (print_ast) {
|
||||
ast->print();
|
||||
}
|
||||
}
|
||||
|
||||
|
91
peglib.h
91
peglib.h
@ -180,6 +180,7 @@ struct SemanticValue
|
||||
|
||||
struct SemanticValues : protected std::vector<SemanticValue>
|
||||
{
|
||||
const char* path;
|
||||
const char* ss;
|
||||
const char* s;
|
||||
size_t n;
|
||||
@ -407,6 +408,7 @@ inline bool fail(size_t len) {
|
||||
*/
|
||||
struct Context
|
||||
{
|
||||
const char* path;
|
||||
const char* s;
|
||||
size_t l;
|
||||
|
||||
@ -423,8 +425,9 @@ struct Context
|
||||
|
||||
std::map<std::pair<size_t, size_t>, std::tuple<size_t, any>> cache_result;
|
||||
|
||||
Context(const char* s, size_t l, size_t def_count, bool enablePackratParsing)
|
||||
: s(s)
|
||||
Context(const char* path, const char* s, size_t l, size_t def_count, bool enablePackratParsing)
|
||||
: path(path)
|
||||
, s(s)
|
||||
, l(l)
|
||||
, error_pos(nullptr)
|
||||
, message_pos(nullptr)
|
||||
@ -475,6 +478,7 @@ struct Context
|
||||
if (!sv.empty()) {
|
||||
sv.clear();
|
||||
}
|
||||
sv.path = path;
|
||||
sv.ss = s;
|
||||
sv.s = nullptr;
|
||||
sv.n = 0;
|
||||
@ -1085,32 +1089,32 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Result parse(const char* s, size_t n) const {
|
||||
Result parse(const char* s, size_t n, const char* path = nullptr) const {
|
||||
SemanticValues sv;
|
||||
any dt;
|
||||
return parse_core(s, n, sv, dt);
|
||||
return parse_core(s, n, sv, dt, path);
|
||||
}
|
||||
|
||||
Result parse(const char* s) const {
|
||||
Result parse(const char* s, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse(s, n);
|
||||
return parse(s, n, path);
|
||||
}
|
||||
|
||||
Result parse(const char* s, size_t n, any& dt) const {
|
||||
Result parse(const char* s, size_t n, any& dt, const char* path = nullptr) const {
|
||||
SemanticValues sv;
|
||||
return parse_core(s, n, sv, dt);
|
||||
return parse_core(s, n, sv, dt, path);
|
||||
}
|
||||
|
||||
Result parse(const char* s, any& dt) const {
|
||||
Result parse(const char* s, any& dt, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse(s, n, dt);
|
||||
return parse(s, n, dt, path);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Result parse_and_get_value(const char* s, size_t n, T& val) const {
|
||||
Result parse_and_get_value(const char* s, size_t n, T& val, const char* path = nullptr) const {
|
||||
SemanticValues sv;
|
||||
any dt;
|
||||
auto r = parse_core(s, n, sv, dt);
|
||||
auto r = parse_core(s, n, sv, dt, path);
|
||||
if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
|
||||
val = sv[0].val.get<T>();
|
||||
}
|
||||
@ -1118,15 +1122,15 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Result parse_and_get_value(const char* s, T& val) const {
|
||||
Result parse_and_get_value(const char* s, T& val, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_and_get_value(s, n, val);
|
||||
return parse_and_get_value(s, n, val, path);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Result parse_and_get_value(const char* s, size_t n, any& dt, T& val) const {
|
||||
Result parse_and_get_value(const char* s, size_t n, any& dt, T& val, const char* path = nullptr) const {
|
||||
SemanticValues sv;
|
||||
auto r = parse_core(s, n, sv, dt);
|
||||
auto r = parse_core(s, n, sv, dt, path);
|
||||
if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
|
||||
val = sv[0].val.get<T>();
|
||||
}
|
||||
@ -1134,9 +1138,9 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Result parse_and_get_value(const char* s, any& dt, T& val) const {
|
||||
Result parse_and_get_value(const char* s, any& dt, T& val, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_and_get_value(s, n, dt, val);
|
||||
return parse_and_get_value(s, n, dt, val, path);
|
||||
}
|
||||
|
||||
Definition& operator=(Action a) {
|
||||
@ -1173,11 +1177,11 @@ private:
|
||||
Definition& operator=(const Definition& rhs);
|
||||
Definition& operator=(Definition&& rhs);
|
||||
|
||||
Result parse_core(const char* s, size_t n, SemanticValues& sv, any& dt) const {
|
||||
Result parse_core(const char* s, size_t n, SemanticValues& sv, any& dt, const char* path) const {
|
||||
AssignIDToDefinition assignId;
|
||||
holder_->accept(assignId);
|
||||
|
||||
Context cxt(s, n, assignId.ids.size(), enablePackratParsing);
|
||||
Context cxt(path, s, n, assignId.ids.size(), enablePackratParsing);
|
||||
auto len = holder_->parse(s, n, sv, cxt, dt);
|
||||
return Result{ success(len), len, cxt.error_pos, cxt.message_pos, cxt.message };
|
||||
}
|
||||
@ -1953,22 +1957,22 @@ inline constexpr unsigned int operator "" _(const char* s, size_t) {
|
||||
|
||||
struct Ast
|
||||
{
|
||||
Ast(size_t line, size_t column, const char* name, const std::vector<std::shared_ptr<Ast>>& nodes)
|
||||
: line(line), column(column), name(name), original_name(name), is_token(false), nodes(nodes)
|
||||
Ast(const char* path, size_t line, size_t column, const char* name, const std::vector<std::shared_ptr<Ast>>& nodes)
|
||||
: path(path), line(line), column(column), name(name), original_name(name), is_token(false), nodes(nodes)
|
||||
#ifdef PEGLIB_HAS_CONSTEXPR_SUPPORT
|
||||
, tag(str2tag(name)), original_tag(tag)
|
||||
#endif
|
||||
{}
|
||||
|
||||
Ast(size_t line, size_t column, const char* name, const std::string& token)
|
||||
: line(line), column(column), name(name), original_name(name), is_token(true), token(token)
|
||||
Ast(const char* path, size_t line, size_t column, const char* name, const std::string& token)
|
||||
: path(path), line(line), column(column), name(name), original_name(name), is_token(true), token(token)
|
||||
#ifdef PEGLIB_HAS_CONSTEXPR_SUPPORT
|
||||
, tag(str2tag(name)), original_tag(tag)
|
||||
#endif
|
||||
{}
|
||||
|
||||
Ast(const Ast& ast, const char* original_name)
|
||||
: line(ast.line), column(ast.column), name(ast.name), original_name(original_name)
|
||||
: path(ast.path), line(ast.line), column(ast.column), name(ast.name), original_name(original_name)
|
||||
, is_token(ast.is_token), token(ast.token), nodes(ast.nodes)
|
||||
#ifdef PEGLIB_HAS_CONSTEXPR_SUPPORT
|
||||
, tag(ast.tag), original_tag(str2tag(original_name))
|
||||
@ -1979,6 +1983,7 @@ struct Ast
|
||||
|
||||
void print() const;
|
||||
|
||||
const std::string path;
|
||||
const size_t line;
|
||||
const size_t column;
|
||||
const std::string name;
|
||||
@ -2079,41 +2084,41 @@ public:
|
||||
return load_grammar(s, n);
|
||||
}
|
||||
|
||||
bool parse_n(const char* s, size_t n) const {
|
||||
bool parse_n(const char* s, size_t n, const char* path = nullptr) const {
|
||||
if (grammar_ != nullptr) {
|
||||
const auto& rule = (*grammar_)[start_];
|
||||
auto r = rule.parse(s, n);
|
||||
auto r = rule.parse(s, n, path);
|
||||
output_log(s, n, log, r);
|
||||
return r.ret && r.len == n;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse(const char* s) const {
|
||||
bool parse(const char* s, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_n(s, n);
|
||||
return parse_n(s, n, path);
|
||||
}
|
||||
|
||||
bool parse_n(const char* s, size_t n, any& dt) const {
|
||||
bool parse_n(const char* s, size_t n, any& dt, const char* path = nullptr) const {
|
||||
if (grammar_ != nullptr) {
|
||||
const auto& rule = (*grammar_)[start_];
|
||||
auto r = rule.parse(s, n, dt);
|
||||
auto r = rule.parse(s, n, dt, path);
|
||||
output_log(s, n, log, r);
|
||||
return r.ret && r.len == n;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse(const char* s, any& dt) const {
|
||||
bool parse(const char* s, any& dt, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_n(s, n, dt);
|
||||
return parse_n(s, n, dt, path);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool parse_n(const char* s, size_t n, T& val) const {
|
||||
bool parse_n(const char* s, size_t n, T& val, const char* path = nullptr) const {
|
||||
if (grammar_ != nullptr) {
|
||||
const auto& rule = (*grammar_)[start_];
|
||||
auto r = rule.parse_and_get_value(s, n, val);
|
||||
auto r = rule.parse_and_get_value(s, n, val, path);
|
||||
output_log(s, n, log, r);
|
||||
return r.ret && r.len == n;
|
||||
}
|
||||
@ -2121,16 +2126,16 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool parse(const char* s, T& val) const {
|
||||
bool parse(const char* s, T& val, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_n(s, n, val);
|
||||
return parse_n(s, n, val, path);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool parse_n(const char* s, size_t n, any& dt, T& val) const {
|
||||
bool parse_n(const char* s, size_t n, any& dt, T& val, const char* path = nullptr) const {
|
||||
if (grammar_ != nullptr) {
|
||||
const auto& rule = (*grammar_)[start_];
|
||||
auto r = rule.parse_and_get_value(s, n, dt, val);
|
||||
auto r = rule.parse_and_get_value(s, n, dt, val, path);
|
||||
output_log(s, n, log, r);
|
||||
return r.ret && r.len == n;
|
||||
}
|
||||
@ -2138,7 +2143,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool parse(const char* s, any& dt, T& val) const {
|
||||
bool parse(const char* s, any& dt, T& val, const char* path = nullptr) const {
|
||||
auto n = strlen(s);
|
||||
return parse_n(s, n, dt, val);
|
||||
}
|
||||
@ -2179,7 +2184,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
peg& enable_ast(bool optimize_nodes, const std::initializer_list<std::string>& filters) {
|
||||
peg& enable_ast(bool optimize_nodes, const std::initializer_list<std::string>& filters = {}) {
|
||||
for (auto& x: *grammar_) {
|
||||
const auto& name = x.first;
|
||||
auto& rule = x.second;
|
||||
@ -2192,14 +2197,14 @@ public:
|
||||
rule.action = [=](const SemanticValues& sv) {
|
||||
if (is_token) {
|
||||
auto line = line_info(sv.ss, sv.s);
|
||||
return std::make_shared<Ast>(line.first, line.second, name.c_str(), std::string(sv.s, sv.n));
|
||||
return std::make_shared<Ast>(sv.path, line.first, line.second, name.c_str(), std::string(sv.s, sv.n));
|
||||
}
|
||||
if (opt && sv.size() == 1) {
|
||||
auto ast = std::make_shared<Ast>(*sv[0].get<std::shared_ptr<Ast>>(), name.c_str());
|
||||
return ast;
|
||||
}
|
||||
auto line = line_info(sv.ss, sv.s);
|
||||
return std::make_shared<Ast>(line.first, line.second, name.c_str(), sv.transform<std::shared_ptr<Ast>>());
|
||||
return std::make_shared<Ast>(sv.path, line.first, line.second, name.c_str(), sv.transform<std::shared_ptr<Ast>>());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user