From 0d04afb5d385bb152c17eabe4b04f5d9f0577f11 Mon Sep 17 00:00:00 2001 From: Daniel Fiser Date: Sun, 14 Oct 2007 23:18:50 +0200 Subject: [PATCH] Created parser and interfaces for creating specific parsers for specific input. --- src/Makefile | 5 +- src/debug.h | 6 + src/main.cpp | 99 ++++--------- src/parser/parser.cpp | 401 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/parser/parser.h | 112 ++++++++++++++ 5 files changed, 548 insertions(+), 75 deletions(-) rewrite src/main.cpp (87%) create mode 100644 src/parser/parser.cpp create mode 100644 src/parser/parser.h diff --git a/src/Makefile b/src/Makefile index 19219d0..5ba02d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,14 +14,15 @@ ALL_FLAGS = $(CXXFLAGS) $(DEBUGFLAGS) $(QT_INCLUDE) ALL_LD_FLAGS = $(QT_LIBS) -VPATH = diff qt +VPATH = diff qt parser TARGETS = qshowdiff DIFF_OBJS = snippet.o diff.o file.o hunk.o text.o QT_OBJS = diff_view.o main_window.o +PARSER_OBJS = parser.o -OBJS_TMP = main.o settings.o $(DIFF_OBJS) $(QT_OBJS) +OBJS_TMP = main.o settings.o $(DIFF_OBJS) $(QT_OBJS) $(PARSER_OBJS) OBJS = $(foreach file, $(OBJS_TMP), objs/$(file)) all: $(TARGETS) diff --git a/src/debug.h b/src/debug.h index 9a09199..56146df 100644 --- a/src/debug.h +++ b/src/debug.h @@ -17,13 +17,19 @@ * ERROR("error" << "message"); */ #ifndef NDEBUG +/* #define DEBUG_HELPER(msg, type) \ std::cerr << __FILE__ << ": " << __LINE__ << ": " << type << ": " \ << msg << std::endl; \ std::cerr.flush() + */ + #define DEBUG_HELPER(msg, type) \ + std::cerr << msg << std::endl; \ + std::cerr.flush() #define DBG(msg) DEBUG_HELPER(msg, "Debug") #define ERROR(msg) DEBUG_HELPER(msg, "Error") #define WARNING(msg) DEBUG_HELPER(msg, "Warning") + #define MILESTONE(msg) DEBUG_HELPER(msg, "Milestone") #else #define DEBUG_HELPER(msg, type) #define DB(msg, type) diff --git a/src/main.cpp b/src/main.cpp dissimilarity index 87% index c9fcf35..ca7850d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,73 +1,26 @@ -#include - -#include "diff/diff.h" -#include "diff/text.h" -#include "qt/main_window.h" -#include "settings.h" - - -void createDiff() -{ - Diff *diff = Diff::instance(); - File *file = new File("filename"); - File *file2 = new File("filename2"); - Hunk *h1 = new Hunk(100, 105); - Hunk *h2 = new Hunk(150, 155); - Hunk *h3 = new Hunk(250, 255); - Text *t1 = new Text(); - Text *t2 = new Text(); - Text *t3 = new Text(); - Text *t4 = new Text(); - - t1->addLine(new QString("Line1 asdlkjf halsjdlfkjahlsdhf laj dsljfh\ - lasjd hflakf jk ahlds jhflaksdkjfa hlsjf hlak dhflkjadslf\ - askjd fl sadfl asld fald sfhlkja sdljfh asd fhalkdjsfhlksa\ - df")); - t1->addLine(new QString("Line2")); - t1->addLine(new QString("Line3")); - t2->addLine(new QString("LLine3")); - t2->addLine(new QString("LLine3")); - t2->addLine(new QString("LLine3")); - t3->addLine(new QString("LLLine3")); - t3->addLine(new QString("LLLine3")); - t3->addLine(new QString("LLLine3")); - t4->addLine(new QString("LLLLine3")); - t4->addLine(new QString("LLLLLine3")); - - h1->addSnippet(new Context(new Text(*t1))); - h1->addSnippet(new Added(new Text(*t2))); - h1->addSnippet(new Context(new Text(*t1))); - - h2->addSnippet(new Deleted(new Text(*t3))); - h2->addSnippet(new Context(new Text(*t1))); - - h3->addSnippet(new Changed(new Text(*t4), new Text(*t3))); - h3->addSnippet(new Added(new Text(*t1))); - h3->addSnippet(new Context(new Text(*t2))); - - file->addHunk(h1); - file->addHunk(h2); - file->addHunk(h3); - - file2->addHunk(new Hunk(*h1)); - file2->addHunk(new Hunk(*h2)); - file2->addHunk(new Hunk(*h3)); - - diff->addFile(file); - diff->addFile(file2); - delete t1; - delete t2; - delete t3; - delete t4; -} - -int main(int argc, char *argv[]) -{ - createDiff(); - - QApplication app(argc, argv); - - MainWindow win; - win.show(); - app.exec(); -} +#include + +#include "diff/diff.h" +#include "diff/text.h" +#include "qt/main_window.h" +#include "settings.h" +#include "parser/parser.h" + + +int main(int argc, char *argv[]) +{ + MILESTONE(""); + MILESTONE("====== START QSHOWDIFF ======"); + + Parser parser("git", new QTextStream(stdin)); + parser.parse(); + + QApplication app(argc, argv); + + MainWindow win; + win.show(); + app.exec(); + + MILESTONE("====== FINISH QSHOWDIFF ======"); + MILESTONE(""); +} diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp new file mode 100644 index 0000000..915523b --- /dev/null +++ b/src/parser/parser.cpp @@ -0,0 +1,401 @@ +#include "parser.h" +#include "../diff/diff.h" + +using namespace std; + +Tokens::Tokens(const char *f_tok, + const char *h_tok, + const char *c_tok, + const char *a_tok, + const char *d_tok) : + file_tok(f_tok), + hunk_tok(h_tok), + context_tok(c_tok), + added_tok(a_tok), + deleted_tok(d_tok){} + +Tokens::token Tokens::match(QString &line) const +{ + if (file_tok.indexIn(line) != -1){ + return FILE_TOK; + }else if (hunk_tok.indexIn(line) != -1){ + return HUNK_TOK; + }else if (context_tok.indexIn(line) != -1){ + return CONTEXT_TOK; + }else if (added_tok.indexIn(line) != -1){ + return ADDED_TOK; + }else if (deleted_tok.indexIn(line) != -1){ + return DELETED_TOK; + } + + return NONE_TOK; +} + +TokensGit::TokensGit() : Tokens::Tokens("^diff --git a/([^ ]+) b/.*$", + "^@@ -([0-9]+),.* \\+([0-9]+),.*$", + "^ .*$", + "^\\+.*$", + "^-.*$"){} + + +/* PARSER */ +// public: +void Parser::parse() +{ + _readNextLine(); + + while (_current_state != END_STATE){ + switch (_current_state){ + case START_STATE: + _start(); + break; + case FILE_STATE: + _file(); + break; + case HUNK_STATE: + _hunk(); + break; + case CONTEXT_STATE: + _context(); + break; + case ADDED_STATE: + _added(); + break; + case DELETED_STATE: + _deleted(); + break; + case CHANGED_STATE: + _changed(); + break; + case END_STATE: + _end(); + break; + } + } +} + +void Parser::_start() +{ + if (_current_token == Tokens::FILE_TOK){ + _changeState(FILE_STATE); + }else{ + _readNextLine(); + } +} + +void Parser::_file() +{ + if (_current_token == Tokens::FILE_TOK){ + _createNewFile(); + _readNextLine(); + }else if (_current_token == Tokens::HUNK_TOK){ + _changeState(HUNK_STATE); + }else{ + _readNextLine(); + } +} + +void Parser::_hunk() +{ + switch (_current_token){ + case Tokens::HUNK_TOK: + _createNewHunk(); + _readNextLine(); + break; + case Tokens::ADDED_TOK: + _changeState(ADDED_STATE); + break; + case Tokens::DELETED_TOK: + _changeState(DELETED_STATE); + break; + case Tokens::CONTEXT_TOK: + _changeState(CONTEXT_STATE); + break; + default: + _readNextLine(); + } +} + +void Parser::_context() +{ + if (_current_token == Tokens::CONTEXT_TOK){ + _addCurrentLineToContext(); + _readNextLine(); + }else{ + _finishContext(); + + switch (_current_token){ + case Tokens::FILE_TOK: + _finishFile(); + _changeState(FILE_STATE); + break; + case Tokens::HUNK_TOK: + _finishHunk(); + _changeState(HUNK_STATE); + break; + case Tokens::ADDED_TOK: + _changeState(ADDED_STATE); + break; + case Tokens::DELETED_TOK: + _changeState(DELETED_STATE); + break; + default: + _changeState(END_STATE); + } + } +} + +void Parser::_added() +{ + if (_current_token == Tokens::ADDED_TOK){ + _addCurrentLineToAdded(); + _readNextLine(); + }else if (_current_token == Tokens::DELETED_TOK){ + _changeState(CHANGED_STATE); + }else{ + _finishAdded(); + + switch (_current_token){ + case Tokens::FILE_TOK: + _finishFile(); + _changeState(FILE_STATE); + break; + case Tokens::HUNK_TOK: + _finishHunk(); + _changeState(HUNK_STATE); + break; + case Tokens::CONTEXT_TOK: + _changeState(CONTEXT_STATE); + break; + default: + _changeState(END_STATE); + } + } +} + +void Parser::_deleted() +{ + if (_current_token == Tokens::DELETED_TOK){ + _addCurrentLineToDeleted(); + _readNextLine(); + }else if (_current_token == Tokens::ADDED_TOK){ + _changeState(CHANGED_STATE); + }else{ + _finishDeleted(); + + switch (_current_token){ + case Tokens::FILE_TOK: + _finishFile(); + _changeState(FILE_STATE); + break; + case Tokens::HUNK_TOK: + _finishHunk(); + _changeState(HUNK_STATE); + break; + case Tokens::CONTEXT_TOK: + _changeState(CONTEXT_STATE); + break; + default: + _changeState(END_STATE); + } + } +} + +void Parser::_changed() +{ + if (_current_token == Tokens::DELETED_TOK){ + _addCurrentLineToDeleted(); + _readNextLine(); + }else if (_current_token == Tokens::ADDED_TOK){ + _addCurrentLineToAdded(); + _readNextLine(); + }else{ + _finishChanged(); + + switch (_current_token){ + case Tokens::FILE_TOK: + _finishFile(); + _changeState(FILE_STATE); + break; + case Tokens::HUNK_TOK: + _finishHunk(); + _changeState(HUNK_STATE); + break; + case Tokens::CONTEXT_TOK: + _changeState(CONTEXT_STATE); + break; + default: + _changeState(END_STATE); + } + } +} + +void Parser::_end() +{ + _finishContext(); + _finishChanged(); + _finishAdded(); + _finishDeleted(); + _finishHunk(); + _finishFile(); + + _changeState(END_STATE); +} + + +// private: +void Parser::_readNextLine() +{ + _current_line = _in->readLine(); + _current_token = _tokens->match(_current_line); + DBG("Read line \"" << _current_line.toStdString() << "\""); +} + +void Parser::_changeState(Parser::states new_state) +{ + _current_state = new_state; +#ifndef NDEBUG + string state; + switch (_current_state){ + case START_STATE: + state = "START_STATE"; + break; + case FILE_STATE: + state = "FILE_STATE"; + break; + case HUNK_STATE: + state = "HUNK_STATE"; + break; + case CONTEXT_STATE: + state = "CONTEXT_STATE"; + break; + case ADDED_STATE: + state = "ADDED_STATE"; + break; + case DELETED_STATE: + state = "DELETED_STATE"; + break; + case CHANGED_STATE: + state = "CHANGED_STATE"; + break; + case END_STATE: + state = "END_STATE"; + break; + } + DBG("State changed to " << state); +#endif +} + + +QString Parser::_capCurrentLine(int cap) +{ + switch (_current_token){ + case Tokens::FILE_TOK: + return _tokens->file_tok.cap(cap); + case Tokens::HUNK_TOK: + return _tokens->hunk_tok.cap(cap); + case Tokens::CONTEXT_TOK: + return _tokens->context_tok.cap(cap); + case Tokens::ADDED_TOK: + return _tokens->added_tok.cap(cap); + case Tokens::DELETED_TOK: + return _tokens->deleted_tok.cap(cap); + case Tokens::NONE_TOK: + return ""; + } + return ""; +} + +void Parser::_createNewFile() +{ + if (_cur_file != NULL) + return; + + Diff::instance()->addFile(_cur_file = new File(_capCurrentLine(1))); +} +void Parser::_finishFile() +{ + _cur_file = NULL; +} + +void Parser::_createNewHunk() +{ + if (_cur_file == NULL || _cur_hunk != NULL) + return; + + int from1, from2; + from1 = _capCurrentLine(1).toInt(); + from2 = _capCurrentLine(2).toInt(); + + _cur_file->addHunk(_cur_hunk = new Hunk(from1, from2)); +} +void Parser::_finishHunk() +{ + _cur_hunk = NULL; +} + +void Parser::_addCurrentLineToContext() +{ + if (_cur_context == NULL) + _cur_context = new Text(); + _cur_context->addLine(new QString(_current_line.remove(0,1))); +} +void Parser::_finishContext() +{ + if (_cur_context == NULL || _cur_hunk == NULL) + return; + _cur_hunk->addSnippet(new Context(_cur_context)); + _cur_context = NULL; +} + +void Parser::_addCurrentLineToAdded() +{ + if (_cur_added == NULL) + _cur_added = new Text(); + _cur_added->addLine(new QString(_current_line.remove(0,1))); +} +void Parser::_finishAdded() +{ + if (_cur_added == NULL || _cur_hunk == NULL){ + return; + } + _cur_hunk->addSnippet(new Added(_cur_added)); + _cur_added = NULL; +} + +void Parser::_addCurrentLineToDeleted() +{ + if (_cur_deleted == NULL) + _cur_deleted = new Text(); + _cur_deleted->addLine(new QString(_current_line.remove(0,1))); +} +void Parser::_finishDeleted() +{ + if (_cur_deleted == NULL || _cur_hunk == NULL){ + return; + } + _cur_hunk->addSnippet(new Deleted(_cur_deleted)); + _cur_deleted = NULL; +} + +void Parser::_finishChanged() +{ + if (_cur_deleted == NULL || _cur_added == NULL || _cur_hunk == NULL){ + return; + } + _cur_hunk->addSnippet(new Changed(_cur_deleted, _cur_added)); + _cur_deleted = NULL; + _cur_added = NULL; +} +/* PARSER END */ + + + +Tokens *factory(string type) +{ + Tokens *ret; + + ret = new TokensGit(); + DBG("factory(" << type << ") - ret: " << (long)ret); + return ret; +} diff --git a/src/parser/parser.h b/src/parser/parser.h new file mode 100644 index 0000000..82306ec --- /dev/null +++ b/src/parser/parser.h @@ -0,0 +1,112 @@ +#ifndef _PARSER_H_ +#define _PARSER_H_ + +#include +#include +#include +#include "../diff/diff.h" + +class Tokens{ + public: + /*{*/ + /** + * Tokens + */ + QRegExp file_tok; + QRegExp hunk_tok; + QRegExp context_tok; + QRegExp added_tok; + QRegExp deleted_tok; + /*}*/ + + protected: + Tokens(const char *file_tok, + const char *hunk_tok, + const char *context_tok, + const char *added_tok, + const char *deleted_tok); + + public: + enum token{ + FILE_TOK, + HUNK_TOK, + CONTEXT_TOK, + ADDED_TOK, + DELETED_TOK, + NONE_TOK + }; + + virtual token match(QString &line) const; +}; + + +class TokensGit : public Tokens{ + public: + TokensGit(); +}; + + +Tokens *factory(std::string); + +class Parser{ + private: + enum states{ + START_STATE = 0, + FILE_STATE, + HUNK_STATE, + CONTEXT_STATE, + ADDED_STATE, + DELETED_STATE, + CHANGED_STATE, + END_STATE + }; + + states _current_state; + QString _current_line; + Tokens::token _current_token; + + QTextStream *_in; + Tokens *_tokens; + + File *_cur_file; + Hunk *_cur_hunk; + Text *_cur_context; + Text *_cur_deleted; + Text *_cur_added; + + void _changeState(states); + void _readNextLine(); + QString _capCurrentLine(int); + + void _createNewFile(); + void _finishFile(); + + void _createNewHunk(); + void _finishHunk(); + + void _addCurrentLineToContext(); + void _finishContext(); + void _addCurrentLineToAdded(); + void _finishAdded(); + void _addCurrentLineToDeleted(); + void _finishDeleted(); + void _finishChanged(); + + void _start(); + void _file(); + void _hunk(); + void _context(); + void _added(); + void _deleted(); + void _changed(); + void _end(); + public: + Parser(std::string type, QTextStream *in) : + _current_state(START_STATE), + _in(in), + _cur_file(NULL), _cur_hunk(NULL), _cur_context(NULL), + _cur_deleted(NULL), _cur_added(NULL) { _tokens = factory(type); } + void parse(); +}; + +#endif -- 2.11.4.GIT