Better error report.

This commit is contained in:
yhirose 2015-05-28 21:36:29 -04:00
parent a7c2de1c32
commit f3f73e5c35
6 changed files with 78 additions and 51 deletions

View File

@ -1,5 +1,6 @@
#include "interpreter.hpp" #include "interpreter.hpp"
#include "parser.hpp" #include "parser.hpp"
#include <sstream>
using namespace peglib; using namespace peglib;
using namespace std; using namespace std;
@ -187,11 +188,20 @@ std::ostream& operator<<(std::ostream& os, const Value& val)
return val.out(os); return val.out(os);
} }
bool run(Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast) bool run(const string& path, Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast)
{ {
try { try {
shared_ptr<Ast> ast; shared_ptr<Ast> ast;
if (get_parser().parse_n(expr, len, ast)) {
auto& parser = get_parser();
parser.log = [&](size_t ln, size_t col, const string& err_msg) {
stringstream ss;
ss << path << ":" << ln << ":" << col << ": " << err_msg << endl;
msg = ss.str();
};
if (parser.parse_n(expr, len, ast)) {
if (print_ast) { if (print_ast) {
ast->print(); ast->print();
} }
@ -199,7 +209,7 @@ bool run(Env& env, const char* expr, size_t len, Value& val, std::string& msg, b
val = Eval::eval(*ast, env); val = Eval::eval(*ast, env);
return true; return true;
} }
} catch (exception& e) { } catch (runtime_error& e) {
msg = e.what(); msg = e.what();
} }

View File

@ -193,4 +193,4 @@ private:
std::map<std::string, Value> dic_; std::map<std::string, Value> dic_;
}; };
bool run(Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast); bool run(const std::string& path, Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast);

View File

@ -44,6 +44,7 @@ int main(int argc, const char** argv)
shell = path_list.empty(); shell = path_list.empty();
} }
try {
Env env; Env env;
env.setup_built_in_functions(); env.setup_built_in_functions();
@ -56,9 +57,8 @@ int main(int argc, const char** argv)
Value val; Value val;
string msg; string msg;
if (!run(env, buff.data(), buff.size(), val, msg, print_ast)) { if (!run(path, env, buff.data(), buff.size(), val, msg, print_ast)) {
cerr << "error in '" << path << "'." << endl; cerr << msg;
cerr << msg.c_str() << endl;
return -1; return -1;
} }
} }
@ -66,6 +66,10 @@ int main(int argc, const char** argv)
if (shell) { if (shell) {
repl(env, print_ast); repl(env, print_ast);
} }
} catch (exception& e) {
cerr << e.what() << endl;
return -1;
}
return 0; return 0;
} }

View File

@ -40,7 +40,24 @@ static auto g_grammar = R"(
Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile) Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile)
)"; )";
static auto g_parser = peg(g_grammar) peglib::peg& get_parser()
{
static peg parser;
static bool initialized = false;
if (!initialized) {
initialized = true;
parser.log = [&](size_t ln, size_t col, const string& msg) {
cerr << ln << ":" << col << ": " << msg << endl;
};
if (!parser.load_grammar(g_grammar)) {
throw logic_error("invalid peg grammar");
}
parser
.ast_node_optimizable("STATEMENTS", Statements) .ast_node_optimizable("STATEMENTS", Statements)
.ast_node("WHILE", While) .ast_node("WHILE", While)
.ast_node("ASSIGNMENT", Assignment) .ast_node("ASSIGNMENT", Assignment)
@ -59,14 +76,10 @@ static auto g_parser = peg(g_grammar)
.ast_token("BOOLEAN", Boolean) .ast_token("BOOLEAN", Boolean)
.ast_token("STRING") .ast_token("STRING")
.ast_token("IDENTIFIER", Identifier) .ast_token("IDENTIFIER", Identifier)
.ast_end() .ast_end();
.set_logger([&](size_t ln, size_t col, const string& msg) { }
cerr << ln << ":" << col << ": " << msg << endl;
});
const peglib::peg& get_parser() return parser;
{
return g_parser;
} }
// vim: et ts=4 sw=4 cin cino={1s ff=unix // vim: et ts=4 sw=4 cin cino={1s ff=unix

View File

@ -6,6 +6,6 @@ enum AstType
Identifier, Number, Boolean, Function Identifier, Number, Boolean, Function
}; };
const peglib::peg& get_parser(); peglib::peg& get_parser();
// vim: et ts=4 sw=4 cin cino={1s ff=unix // vim: et ts=4 sw=4 cin cino={1s ff=unix

View File

@ -16,11 +16,11 @@ int repl(Env& env, bool print_ast)
if (!line.empty()) { if (!line.empty()) {
Value val; Value val;
string msg; string msg;
if (run(env, line.c_str(), line.size(), val, msg, print_ast)) { if (run("(repl)", env, line.c_str(), line.size(), val, msg, print_ast)) {
cout << val << endl; cout << val << endl;
linenoise::AddHistory(line.c_str()); linenoise::AddHistory(line.c_str());
} else if (!msg.empty()) { } else if (!msg.empty()) {
cout << msg << endl; cout << msg;
} }
} }
} }