Crazed attempts at getting line number info.

git-svn-id: file:///srv/svn/ircclient/trunk@10 a9804ffe-773b-11dd-bd7c-89c3ef1d2733
This commit is contained in:
Correl Roush 2009-05-05 18:14:05 +00:00
parent 8d1a03d239
commit 0e773a5687
8 changed files with 71 additions and 21 deletions

View file

@ -24,6 +24,9 @@ private:
QMap<QString,void (*)(QStringList)> internal_aliases; QMap<QString,void (*)(QStringList)> internal_aliases;
QString _return_value; QString _return_value;
QTextStream *output; QTextStream *output;
MIRCScript* current_script;
int line_offset;
public: public:
MIRCScriptManager(QObject *parent = 0); MIRCScriptManager(QObject *parent = 0);

View file

@ -14,6 +14,7 @@
#include <boost/spirit/core.hpp> #include <boost/spirit/core.hpp>
#include <boost/spirit/utility/confix.hpp> #include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/dynamic/if.hpp> #include <boost/spirit/dynamic/if.hpp>
#include <boost/spirit/iterator/position_iterator.hpp>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@ -28,12 +29,15 @@ using namespace boost;
using namespace boost::spirit; using namespace boost::spirit;
typedef QMap<QString, QString> mirc_variables; typedef QMap<QString, QString> mirc_variables;
typedef position_iterator<char const*> iterator_t;
struct mirc_alias { struct mirc_alias {
mirc_alias(bool _global = true) { mirc_alias(int _line = 0, bool _global = true) {
line = _line;
global = _global; global = _global;
} }
bool global; bool global;
int line;
QString code; QString code;
}; };
@ -60,13 +64,17 @@ public:
mirc_alias script; mirc_alias script;
mirc_aliases aliases; mirc_aliases aliases;
mirc_variables vars; mirc_variables vars;
int line;
mirc_script_engine(MIRCScriptManager *m); mirc_script_engine(MIRCScriptManager *m);
void set_stage(mirc_engine_stage _stage);
void handle_alias_definition(char const* str, char const* end); void handle_alias_definition(char const* str, char const* end);
void handle_alias_definition_local(char const* str, char const* end); void handle_alias_definition_local(char const* str, char const* end);
void close_alias(char const*, char const*); void close_alias(char const*, char const*);
void store_code(char const* str, char const* end); void store_code(char const* str, char const* end);
void code_line(char const* str, char const* end);
void set_alias(char const* str, char const* end); void set_alias(char const* str, char const* end);
void call_alias(char const*, char const*); void call_alias(char const*, char const*);
void return_alias(char const*, char const*); void return_alias(char const*, char const*);
@ -120,6 +128,7 @@ struct mirc_script : public grammar<mirc_script> {
s_action v_append ( bind( &mirc_script_engine::append_value, self.actions, _1, _2 ) ); s_action v_append ( bind( &mirc_script_engine::append_value, self.actions, _1, _2 ) );
s_action e_append ( bind( &mirc_script_engine::append_expression, self.actions, _1, _2 ) ); s_action e_append ( bind( &mirc_script_engine::append_expression, self.actions, _1, _2 ) );
s_action s_code ( bind( &mirc_script_engine::store_code, self.actions, _1, _2 ) ); s_action s_code ( bind( &mirc_script_engine::store_code, self.actions, _1, _2 ) );
s_action c_line (bind( &mirc_script_engine::code_line, self.actions, _1, _2 ) );
s_action c_stack ( bind( &mirc_script_engine::clear_stack, self.actions, _1, _2 ) ); s_action c_stack ( bind( &mirc_script_engine::clear_stack, self.actions, _1, _2 ) );
script script
@ -130,7 +139,7 @@ struct mirc_script : public grammar<mirc_script> {
; ;
space space
= ( blank_p = ( blank_p
| str_p("$&") >> *blank_p >> eol_p | str_p("$&") >> *blank_p >> eol_p[c_line]
) )
; ;
nospace nospace
@ -183,23 +192,23 @@ struct mirc_script : public grammar<mirc_script> {
alias_definition alias_definition
= str_p("alias") >> *space = str_p("alias") >> *space
>> if_p(str_p("-l") >> *space)[identifier[l_def]].else_p[identifier[a_def]] >> if_p(str_p("-l") >> *space)[identifier[l_def]].else_p[identifier[a_def]]
>> *space >> !eol_p >> *space >> !eol_p[c_line]
>> code_block >> code_block
; ;
code_line code_line
= *space = *space
>> ( comment >> ( comment[c_line]
| ( | (
assignment /* Must come first to avoid "var" being caught as an action */ assignment /* Must come first to avoid "var" being caught as an action */
| alias_action | alias_action
)[s_code] )[s_code]
)[c_stack] )[c_stack]
>> !eol_p >> !eol_p[c_line]
; ;
code_block code_block
= ( *space >> ch_p('{') >> *space >> !eol_p = ( *space >> ch_p('{') >> *space >> !eol_p[c_line]
>> (*code_line) >> (*code_line)
>> ch_p('}') >> *space >> !eol_p >> ch_p('}') >> *space >> !eol_p[c_line]
) )
| code_line | code_line
; ;

View file

@ -16,6 +16,8 @@ private:
QMap<QString, QString> _variables; QMap<QString, QString> _variables;
mirc_script_engine *interpreter; mirc_script_engine *interpreter;
mirc_script *parser; mirc_script *parser;
iterator_t *begin;
iterator_t *end;
bool loaded; bool loaded;
public: public:
MIRCScript(MIRCScriptManager *m); MIRCScript(MIRCScriptManager *m);
@ -25,6 +27,7 @@ public:
bool run(QString alias); bool run(QString alias);
QString code(); QString code();
QString code(QString alias); QString code(QString alias);
int line();
QMap<QString, mirc_alias> aliases(); QMap<QString, mirc_alias> aliases();
QMap<QString, QString> variables(); QMap<QString, QString> variables();
}; };

View file

@ -1,26 +1,25 @@
#include <QTextStream> #include <QTextStream>
#include <QDebug>
#include "script.h" #include "script.h"
QTextStream output(stdout);
void alias_echo(QStringList arguments) { void alias_echo(QStringList arguments) {
output << "[ECHO] " << arguments.join(" ") << "\n"; qDebug() << "[ECHO] " << arguments.join(" ");
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
output << "* Creating manager\n"; // qDebug() << "* Creating manager\n";
MIRCScriptManager *mirc = new MIRCScriptManager; MIRCScriptManager *mirc = new MIRCScriptManager;
mirc->register_alias("echo", &alias_echo); mirc->register_alias("echo", &alias_echo);
if (argc < 2) { if (argc < 2) {
output << "! No mIRC script file was specified!\n"; qDebug() << "! No mIRC script file was specified!\n";
return(1); return(1);
} }
output << "* Attempting to load " << argv[1] << "\n"; // qDebug() << "* Attempting to load " << argv[1] << "\n";
if (mirc->load(argv[1])) { if (mirc->load(argv[1])) {
// ?? // ??
} else { } else {
output << "Failed to load " << argv[1] << "\n"; qDebug() << "Failed to load " << argv[1] << "\n";
return(1); return(1);
} }
return 0; return 0;

View file

@ -2,12 +2,14 @@
MIRCScriptManager::MIRCScriptManager(QObject *parent) { MIRCScriptManager::MIRCScriptManager(QObject *parent) {
this->parent = parent; this->parent = parent;
line_offset = 0;
} }
bool MIRCScriptManager::load(QString filename) { bool MIRCScriptManager::load(QString filename) {
MIRCScript *script = new MIRCScript(this); MIRCScript *script = new MIRCScript(this);
if (script->load(filename)) { if (script->load(filename)) {
scripts << script; scripts << script;
current_script = script;
script->run(); script->run();
return true; return true;
} }
@ -35,10 +37,10 @@ void MIRCScriptManager::call_alias(QString alias, QStringList arguments) {
if (internal_aliases.find(alias) != internal_aliases.end()) { if (internal_aliases.find(alias) != internal_aliases.end()) {
internal_aliases[alias](arguments); internal_aliases[alias](arguments);
} else { } else {
//TODO: check known scripted aliases!!!
// Handle some builtins // Handle some builtins
if (alias == "lower") { if (alias == "line") {
return_value(QString::number(current_script->line() + line_offset));
} else if (alias == "lower") {
return_value(arguments.join(" ").toLower()); return_value(arguments.join(" ").toLower());
} else if (alias == "return") { } else if (alias == "return") {
return_value(arguments.join(" ")); return_value(arguments.join(" "));
@ -58,12 +60,18 @@ void MIRCScriptManager::call_alias(QString alias, QStringList arguments) {
} }
if (found) { if (found) {
MIRCScript *s = new MIRCScript(this); MIRCScript *s = new MIRCScript(this);
MIRCScript *p = current_script;
int offset = line_offset;
line_offset = scripts.at(script_index)->aliases()[alias].line;
current_script = s;
QString code = scripts.at(script_index)->code(alias); QString code = scripts.at(script_index)->code(alias);
if (s->parse(code)) { if (s->parse(code)) {
s->run(); s->run();
} else { } else {
qDebug() << "SYNTAX ERROR IN " << alias; qDebug() << "SYNTAX ERROR IN " << alias;
} }
current_script = p;
line_offset = offset;
delete s; delete s;
} else { } else {
qDebug() << "UNKNOWN ALIAS" << alias; qDebug() << "UNKNOWN ALIAS" << alias;

View file

@ -4,24 +4,29 @@
mirc_script_engine::mirc_script_engine(MIRCScriptManager *m) : script() { mirc_script_engine::mirc_script_engine(MIRCScriptManager *m) : script() {
manager = m; manager = m;
stage = PARSE; set_stage(PARSE);
current_alias = aliases.end(); current_alias = aliases.end();
current_variable = vars.end(); current_variable = vars.end();
} }
void mirc_script_engine::set_stage(mirc_engine_stage _stage) {
this->stage = _stage;
this->line = 1;
}
void mirc_script_engine::handle_alias_definition(char const* str, char const* end) { void mirc_script_engine::handle_alias_definition(char const* str, char const* end) {
if (stage != PARSE) return; if (stage != PARSE) return;
string s(str, end); string s(str, end);
QString alias(s.c_str()); QString alias(s.c_str());
this->aliases.insert(alias, mirc_alias(true)); this->aliases.insert(alias, mirc_alias(line, true));
current_alias = this->aliases.find(alias); current_alias = this->aliases.find(alias);
} }
void mirc_script_engine::handle_alias_definition_local(char const* str, char const* end) { void mirc_script_engine::handle_alias_definition_local(char const* str, char const* end) {
if (stage != PARSE) return; if (stage != PARSE) return;
string s(str, end); string s(str, end);
aliases.insert(s.c_str(), mirc_alias(false)); aliases.insert(s.c_str(), mirc_alias(line, false));
current_alias = aliases.find(s.c_str()); current_alias = aliases.find(s.c_str());
} }
void mirc_script_engine::close_alias(char const*, char const*) { void mirc_script_engine::close_alias(char const*, char const*) {
@ -41,6 +46,9 @@ void mirc_script_engine::store_code(char const* str, char const* end) {
script.code.append(s.c_str()).append("\n"); script.code.append(s.c_str()).append("\n");
} }
} }
void mirc_script_engine::code_line(char const* str, char const* end) {
line++;
}
void mirc_script_engine::set_alias(char const* str, char const* end) { void mirc_script_engine::set_alias(char const* str, char const* end) {
string s(str, end); string s(str, end);
_alias = s.c_str(); _alias = s.c_str();

View file

@ -19,6 +19,7 @@ bool MIRCScript::load(QString filename) {
} }
bool MIRCScript::parse(QString code) { bool MIRCScript::parse(QString code) {
const char* _code = code.toLatin1();
parse_info<> info = boost::spirit::parse((const char*)code.toLatin1(), *parser); parse_info<> info = boost::spirit::parse((const char*)code.toLatin1(), *parser);
loaded = info.full; loaded = info.full;
if (loaded) { if (loaded) {
@ -30,7 +31,18 @@ bool MIRCScript::parse(QString code) {
bool MIRCScript::run() { bool MIRCScript::run() {
if (!loaded) return false; if (!loaded) return false;
interpreter->stage = EXECUTE; interpreter->set_stage(EXECUTE);
// interpreter->stage = EXECUTE;
// interpreter->line = 0;
// iterator_t begin(_code, _code+strlen(_code));
// iterator_t end;
/* Doing it this way affects all the damned callbacks...
const char* _code = (const char*)script.toLatin1();
begin = new iterator_t(_code, _code+strlen(_code));
end = new iterator_t();
parse_info<iterator_t> info = boost::spirit::parse(*begin, *end, *parser);
*/
parse_info<> info = boost::spirit::parse((const char*)script.toLatin1(), *parser); parse_info<> info = boost::spirit::parse((const char*)script.toLatin1(), *parser);
if (info.full) { if (info.full) {
_variables = interpreter->vars; _variables = interpreter->vars;
@ -55,6 +67,10 @@ QString MIRCScript::code(QString alias) {
} }
} }
int MIRCScript::line() {
return interpreter->line;
}
QMap<QString, mirc_alias> MIRCScript::aliases() { QMap<QString, mirc_alias> MIRCScript::aliases() {
return _aliases; return _aliases;
} }

View file

@ -1,4 +1,7 @@
; Hey, here's some test code ; Hey, here's some test code
echo TEST Code line match [ 2 = $line ]
; Test comment
echo TEST Code line match [ 4 = $line ]
set name Correl set name Correl
%first = Correl %first = Correl
%middle = Joseph %middle = Joseph
@ -19,5 +22,6 @@ alias -l getversion {
} }
alias -l showversion { alias -l showversion {
echo You're testing Mercenary $getversion echo You're testing Mercenary $getversion
echo TEST Code line match [ 23 = $line ]
} }
dostuff dostuff