Skip to content
Permalink
Browse files

Output batch items are independent changes; better IncParser API, and…

… many new tests.
  • Loading branch information
nfomon committed Jul 2, 2015
1 parent f6eef9e commit 988204ec5f49b7962a0abd6f22c0f906ff03b751
@@ -21,8 +21,8 @@ using std::auto_ptr;
using namespace exstatik;

auto_ptr<Rule> exstatik::CreateLexer_Simple() {
auto_ptr<Rule> lexer(STAR("lexer"));
Rule* or_ = lexer->AddChild(OR("Or"));
auto_ptr<Rule> lexer(STAR("star"));
Rule* or_ = lexer->AddChild(OR("or"));
or_->AddChild(KEYWORD("new"));
or_->AddChild(KEYWORD("del"));
//or_->AddChild(KEYWORD("x"));
@@ -87,16 +87,17 @@ int main(int argc, char *argv[]) {
parsers.push_back(new IncParser(auto_ptr<Rule>(c.release()), name, graphdir));
}

INode start = NULL;
INode prev = NULL;
const List* start = NULL;
const List* prev = NULL;
string line;
while (getline(cin, line)) {
//line += "\n";
for (size_t i=0; i < line.size(); ++i) {
string c = string(1, line.at(i));
g_log.info();
g_log.info() << "* main: Inserting character '" << c << "'";
INode node = parsers.at(0).Insert(List("", c), prev);
const List* node = new List("", c);
parsers.at(0).Insert(*node, prev);
if (!start) { start = node; }
Batch batch;
parsers.front().ExtractChanges(batch);
@@ -114,9 +115,9 @@ int main(int argc, char *argv[]) {
}
}
g_log.info() << "Clearing input";
List* i = start;
const List* i = start;
while (i) {
List* j = i->right;
const List* j = i->right;
delete i;
i = j;
}
@@ -61,7 +61,7 @@ void IStatik::run() {
exstatik::Compiler::auto_type c = compiler->release(compiler->begin());
string name = c->Name();
g_log.info() << "Adding parser window for " << name;
parserWindows.push_back(new ParserWindow(auto_ptr<statik::Rule>(c.release()), name, m_graphdir));
parserWindows.push_back(new ParserWindow(auto_ptr<statik::Rule>(c.release()), m_compiler_name, m_graphdir));
}

bool done = false;
@@ -189,7 +189,7 @@ WindowResponse LineBuf::Insert(int y, int x, int ch) {
x = 0;
++y;
} while ((size_t)y < m_lines.size());
response.batch.Insert(c->inode);
response.batch.Insert(c->inode, (prev ? &prev->inode : NULL));
if (prev) {
g_log.info() << " found before: " << *prev;
prev->SetNext(c);
@@ -5,13 +5,15 @@

#include "ISError.h"

#include "statik/Batch.h"
#include "statik/List.h"
using statik::Batch;
using statik::List;

#include <memory>
#include <string>
#include <iostream>
#include <utility>
using std::auto_ptr;
using std::endl;
using std::string;

using namespace istatik;
@@ -23,29 +25,92 @@ ParserWindow::ParserWindow(auto_ptr<statik::Rule> rule,
g_log.info() << "Initialized ParserWindow " << name;
}

WindowResponse ParserWindow::Input(const statik::Batch& ibatch) {
ParserWindow::~ParserWindow() {
List* n = m_nodes;
while (n) {
List* prev = n;
n = n->right;
delete prev;
}
}

WindowResponse ParserWindow::Input(const Batch& ibatch) {
g_log.info() << "Updating incParser " << m_incParser.Name() << " with batch: " << ibatch.Print();
m_incParser.ApplyBatch(ibatch);
WindowResponse response;
// Find first item in incParser's output list, and draw everything
response.actions.push_back(WindowAction(WindowAction::MOVE, 0, 0, 0));
statik::Batch batch;
Batch batch;
m_incParser.ExtractChanges(batch);
g_log.info() << "Printing WindowResponse list. Batch size is: " << batch.Size();
if (!batch.IsEmpty()) {
const statik::List* inode = m_incParser.GetFirstONode();
for (Batch::batch_iter i = batch.begin(); i != batch.end(); ++i) {
switch (i->op) {
case Batch::OP_INSERT: {
g_log.debug() << "Insert node: " << i->node->name << ":" << i->node->value;
List* node = new List(i->node->name, i->node->value);
if (i->pos) {
node_iter pos_i = m_nodeMap.find(i->pos);
if (m_nodeMap.end() == pos_i) {
throw ISError("Received invalid pos for Insert");
}
List* pos = pos_i->second;
g_log.debug() << " - at pos: " << pos->name << ":" << pos->value;
node->right = pos->right;
node->left = pos;
pos->right = node;
} else {
node->right = m_nodes;
m_nodes = node;
}
m_nodeMap.insert(std::make_pair(i->node, node));
}
break;
case Batch::OP_DELETE: {
g_log.debug() << "Delete node: " << i->node->name << ":" << i->node->value;
node_mod_iter node_i = m_nodeMap.find(i->node);
if (m_nodeMap.end() == node_i) {
throw ISError("Received invalid node for Delete");
}
List* node = node_i->second;
if (node->left) {
node->left->right = node->right;
if (node->right) {
node->right->left = node->left;
}
delete node;
} else {
if (m_nodes != node) {
throw ISError("Attempt to delete node which has no left, but is not m_nodes either");
}
m_nodes = node->right;
delete node;
}
m_nodeMap.erase(node_i);
}
break;
case Batch::OP_UPDATE:
g_log.debug() << "Update node: " << i->node->name << ":" << i->node->value;
break;
default:
throw ISError("Unknown batch operation " + Batch::UnMapBatchOp(i->op));
}
}

string old_str = m_str;
m_str = "";
bool first = true;
while (inode) {
List* node = m_nodes;
while (node) {
if (first) {
first = false;
} else {
m_str += " ";
}
m_str += inode->name;
inode = inode->right;
m_str += node->name;
node = node->right;
}
g_log.info() << "Printing str: '" << m_str << "'";
for (size_t i = 0; i < m_str.size(); ++i) {
response.actions.push_back(WindowAction(WindowAction::INSERT, 0, i, m_str[i]));
}
@@ -9,10 +9,12 @@

#include "statik/Batch.h"
#include "statik/IncParser.h"
#include "statik/List.h"
#include "statik/Rule.h"

#include <boost/noncopyable.hpp>

#include <map>
#include <memory>

namespace istatik {
@@ -22,10 +24,17 @@ class ParserWindow : private boost::noncopyable {
ParserWindow(std::auto_ptr<statik::Rule> rule,
const std::string& name,
const std::string& graphdir);
~ParserWindow();
WindowResponse Input(const statik::Batch& batch);
private:
statik::IncParser m_incParser;
std::string m_str;
statik::List* m_nodes; // our own copies of the IncParser's ONodes
// maps IncParser's ONode -> our m_nodes
typedef std::map<const statik::List*, statik::List*> node_map;
typedef node_map::const_iterator node_iter;
typedef node_map::iterator node_mod_iter;
node_map m_nodeMap;
};

}
@@ -20,16 +20,16 @@ std::string Batch::UnMapBatchOp(const BATCH_OP& op) {
}
}

void Batch::Insert(const List& inode) {
m_batch.push_back(std::make_pair(&inode, OP_INSERT));
void Batch::Insert(const List& inode, const List* pos = NULL) {
m_batch.push_back(BatchItem(inode, OP_INSERT, pos));
}

void Batch::Delete(const List& inode) {
m_batch.push_back(std::make_pair(&inode, OP_DELETE));
m_batch.push_back(BatchItem(inode, OP_DELETE));
}

void Batch::Update(const List& inode) {
m_batch.push_back(std::make_pair(&inode, OP_UPDATE));
m_batch.push_back(BatchItem(inode, OP_UPDATE));
}

void Batch::Accept(const Batch& batch) {
@@ -46,7 +46,7 @@ void Batch::Clear() {
string Batch::Print() const {
string s;
for (batch_iter i = m_batch.begin(); i != m_batch.end(); ++i) {
s += "\n" + UnMapBatchOp(i->second) + " - " + string(*i->first);
s += "\n" + UnMapBatchOp(i->op) + " - " + string(*i->node);
}
return s;
}
@@ -35,16 +35,23 @@ class Batch {

static std::string UnMapBatchOp(const BATCH_OP& op);

typedef std::pair<const List*, BATCH_OP> batchpair;
typedef std::vector<batchpair> batch_vec;
struct BatchItem {
BatchItem(const List& node, BATCH_OP op, const List* pos = NULL)
: node(&node), op(op), pos(pos) {}
const List* node;
BATCH_OP op;
const List* pos;
};

typedef std::vector<BatchItem> batch_vec;
typedef batch_vec::const_iterator batch_iter;

batch_iter begin() const { return m_batch.begin(); }
batch_iter end() const { return m_batch.end(); }
size_t Size() const { return m_batch.size(); }
bool IsEmpty() const { return m_batch.empty(); }

void Insert(const List& inode);
void Insert(const List& inode, const List* pos);
void Update(const List& inode);
void Delete(const List& inode);
void Accept(const Batch& batch);
@@ -12,6 +12,7 @@
#include "util/Graphviz.h"
#include "util/Util.h"
using Util::dotVar;
using Util::safeLabelStr;

#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
@@ -74,17 +75,6 @@ void Grapher::AddSTree(const string& context, const STree& snode, const string&
m_isDirty = true;
}

void Grapher::AddOList(const string& context, const List& onode, const string& label) {
m_graph += "subgraph cluster_" + context + dotVar(&onode, context) + " {\n";
if (!label.empty()) {
m_graph += "label=\"" + label + "\";\n";
m_graph += "fontsize=12.0;\n";
}
m_graph += onode.DrawNode(context);
m_graph += "}\n";
m_isDirty = true;
}

void Grapher::AddIListeners(const string& context, const IncParser& incParser, const List& inode) {
IncParser::listener_set ls = incParser.GetListeners(inode);
for (IncParser::listener_iter i = ls.begin(); i != ls.end(); ++i) {
@@ -96,10 +86,20 @@ void Grapher::AddIListeners(const string& context, const IncParser& incParser, c
m_isDirty = true;
}

void Grapher::AddBatch(const string& context, const Batch& batch) {
void Grapher::AddOBatch(const string& context, const Batch& batch, const string& label) {
if (batch.IsEmpty()) {
return;
}
const List& start = *batch.begin()->node;
m_graph += "subgraph cluster_" + context + dotVar(&start, context) + " {\n";
if (!label.empty()) {
m_graph += "label=\"" + label + "\";\n";
m_graph += "fontsize=12.0;\n";
}

for (Batch::batch_iter i = batch.begin(); i != batch.end(); ++i) {
string color = "#770000";
switch (i->second) {
switch (i->op) {
case Batch::OP_INSERT:
color = "#00bb44";
break;
@@ -112,9 +112,15 @@ void Grapher::AddBatch(const string& context, const Batch& batch) {
default:
throw SError("Cannot add batch to Grapher: unknown operation");
}
m_graph += dotVar(i->first, context) + " [color=\"" + color + "\", penwidth=4.0];\n";
m_isDirty = true;
const List& node = *i->node;
m_graph += dotVar(&node, context) + " [label=\"" + Util::safeLabelStr(node.name + (node.value.empty() ? "" : (node.name.empty() ? "" : ":") + node.value)) + "\", style=\"filled\", fillcolor=\"#dddddd\", fontsize=12.0, color=\"" + color + "\", penwidth=4.0];\n";
if (i+1 != batch.end()) {
const List& next = *(i+1)->node;
m_graph += dotVar(&node, context) + " -> " + dotVar(&next, context) + ";\n";
}
}
m_graph += "}\n";
m_isDirty = true;
}

void Grapher::Signal(const string& context, const void* x, bool isUpdate) {
@@ -21,9 +21,8 @@ class Grapher {
void AddOrderList(const std::string& context, const OrderList& orderList, const List& start);
void AddIList(const std::string& context, const List& start, const std::string& label = "");
void AddSTree(const std::string& context, const STree& root, const std::string& label = "", const STree* initiator = NULL);
void AddOList(const std::string& context, const List& start, const std::string& label = "");
void AddIListeners(const std::string& context, const IncParser& incParser, const List& start);
void AddBatch(const std::string& context, const Batch& batch);
void AddOBatch(const std::string& context, const Batch& batch, const std::string& label = "");
void Signal(const std::string& context, const void*, bool isUpdate = false);

bool IsDirty() const { return m_isDirty; }

0 comments on commit 988204e

Please sign in to comment.
You can’t perform that action at this time.