From 6980c1e9988a7c959876ad77b760e042272a9ec2 Mon Sep 17 00:00:00 2001 From: Robert Bieber Date: Sat, 29 May 2010 00:04:04 +0000 Subject: Theme Editor: Got code generation tentatively working along with a solid C++ tree structure for WPS parse trees git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26367 a1c6a512-1295-4272-9138-f99709370657 --- utils/themeeditor/main.cpp | 15 ++- utils/themeeditor/parsetreemodel.cpp | 11 +- utils/themeeditor/parsetreemodel.h | 6 +- utils/themeeditor/parsetreenode.cpp | 228 +++++++++++++++++++++++++++-------- utils/themeeditor/parsetreenode.h | 40 ++++-- utils/themeeditor/skin_parser.c | 26 ++-- utils/themeeditor/skin_parser.h | 10 +- 7 files changed, 245 insertions(+), 91 deletions(-) (limited to 'utils') diff --git a/utils/themeeditor/main.cpp b/utils/themeeditor/main.cpp index 49e870c369..27ce2da23f 100644 --- a/utils/themeeditor/main.cpp +++ b/utils/themeeditor/main.cpp @@ -27,6 +27,7 @@ extern "C" #include #include +#include #include #include @@ -36,15 +37,21 @@ extern "C" int main(int argc, char* argv[]) { - char doc[] = "%Vd(U);Hey\n%?bl(test,3,5,2,1)"; + char doc[] = "#Comment\n%Vd(U);Hey\n%?bl(test,3,5,2,1)"; struct skin_element* test = skin_parse(doc); - skin_debug_tree(test); + ParseTreeNode tree(test); + std::cout << "----" << std::endl; + if(std::string(doc) == tree.genCode().toStdString()) + std::cout << "Code in/out matches" << std::endl; + else + std::cout << "Match error" << std::endl; - skin_free_tree(test); + skin_free_tree(test); +/* QApplication app(argc, argv); QTreeView tree; @@ -53,7 +60,7 @@ int main(int argc, char* argv[]) tree.show(); return app.exec(); - +*/ return 0; } diff --git a/utils/themeeditor/parsetreemodel.cpp b/utils/themeeditor/parsetreemodel.cpp index aa5fb5cdb8..c99f166c41 100644 --- a/utils/themeeditor/parsetreemodel.cpp +++ b/utils/themeeditor/parsetreemodel.cpp @@ -26,8 +26,8 @@ ParseTreeModel::ParseTreeModel(char* wps, QObject* parent): QAbstractItemModel(parent) { - this->wps = skin_parse(wps); - this->root = new ParseTreeNode(this->wps, 0, true); + this->tree = skin_parse(wps); + this->root = new ParseTreeNode(tree, 0); } @@ -36,6 +36,12 @@ ParseTreeModel::~ParseTreeModel() delete root; } +QString genCode() +{ + return QString(); +} + +/* QModelIndex ParseTreeModel::index(int row, int column, const QModelIndex& parent) const { @@ -98,3 +104,4 @@ QVariant ParseTreeModel::data(const QModelIndex &index, int role) const ParseTreeNode* item = static_cast(index.internalPointer()); return item->data(index.column()); } +*/ diff --git a/utils/themeeditor/parsetreemodel.h b/utils/themeeditor/parsetreemodel.h index 78484eb5f4..64365ed038 100644 --- a/utils/themeeditor/parsetreemodel.h +++ b/utils/themeeditor/parsetreemodel.h @@ -43,15 +43,19 @@ public: ParseTreeModel(char* wps, QObject* parent = 0); virtual ~ParseTreeModel(); + QString genCode(); + + /* QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex parent(const QModelIndex &child) const; int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; + */ private: ParseTreeNode* root; - struct skin_element* wps; + struct skin_element* tree; }; diff --git a/utils/themeeditor/parsetreenode.cpp b/utils/themeeditor/parsetreenode.cpp index 77ec897dd7..ccfac615be 100644 --- a/utils/themeeditor/parsetreenode.cpp +++ b/utils/themeeditor/parsetreenode.cpp @@ -1,74 +1,200 @@ -#include "parsetreenode.h" +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ -ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent, - bool tree) +extern "C" { +#include "symbols.h" +} - if(tree) - { - while(data) - { - appendChild(new ParseTreeNode(data, this, false)); - data = data->next; - } - parentLink = 0; - } - else +#include "parsetreenode.h" + +/* Root element constructor */ +ParseTreeNode::ParseTreeNode(struct skin_element* data) + : parent(0), element(0), param(0), children() +{ + while(data) { - element = data; - parentLink = parent; + children.append(new ParseTreeNode(data, this)); + data = data->next; } - } -ParseTreeNode::ParseTreeNode(struct skin_tag_parameter* param, - ParseTreeNode* parent) - :parentLink(parent), element(0), param(param) +/* Normal element constructor */ +ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent) + : parent(parent), element(data), param(0), children() { + switch(element->type) + { -} + case TAG: + for(int i = 0; i < element->params_count; i++) + { + if(element->params[i].type == skin_tag_parameter::CODE) + children.append(new ParseTreeNode(element->params[i].data.code, + this)); + else + children.append(new ParseTreeNode(&element->params[i], this)); + } + break; + /* CONDITIONAL and SUBLINES fall through to the same code */ + case CONDITIONAL: + case SUBLINES: + for(int i = 0; i < element->children_count; i++) + { + children.append(new ParseTreeNode(data->children[i], this)); + } + break; -ParseTreeNode::~ParseTreeNode() -{ - qDeleteAll(children); -} + case LINE: + for(struct skin_element* current = data->children[0]; current; + current = current->next) + { + children.append(new ParseTreeNode(current, this)); + } + break; -void ParseTreeNode::appendChild(ParseTreeNode* child) -{ - children.append(child); + default: + break; + } } -ParseTreeNode* ParseTreeNode::child(int row) +/* Parameter constructor */ +ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent) + : parent(parent), element(0), param(data), children() { - return children[row]; -} -int ParseTreeNode::childCount() const -{ - return children.count(); } -int ParseTreeNode::columnCount() const +QString ParseTreeNode::genCode() const { - return 2; -} + QString buffer = ""; -QVariant ParseTreeNode::data(int column) const -{ - if(column == 0) - return element->type; + if(element) + { + switch(element->type) + { + case LINE: + for(int i = 0; i < children.count(); i++) + { + /* + Adding a % in case of tag, because the tag rendering code + doesn't insert its own + */ + if(children[i]->element->type == TAG) + buffer.append(TAGSYM); + buffer.append(children[i]->genCode()); + } + break; + + case SUBLINES: + for(int i = 0; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(MULTILINESYM); + } + break; + + case CONDITIONAL: + /* Inserts a %?, the tag renderer doesn't deal with the TAGSYM */ + buffer.append(TAGSYM); + buffer.append(CONDITIONSYM); + buffer.append(children[0]->genCode()); + + /* Inserting the sublines */ + buffer.append(ENUMLISTOPENSYM); + for(int i = 1; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(ENUMLISTSEPERATESYM); + } + buffer.append(ENUMLISTCLOSESYM); + break; + + case TAG: + /* When generating code, we DO NOT insert the leading TAGSYM, leave + * the calling functions to handle that + */ + buffer.append(element->name); + + if(element->params_count > 0) + { + /* Rendering parameters if there are any */ + buffer.append(ARGLISTOPENSYM); + for(int i = 0; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(ARGLISTSEPERATESYM); + } + buffer.append(ARGLISTCLOSESYM); + } + break; + + case NEWLINE: + buffer.append('\n'); + break; + + case TEXT: + buffer.append(element->text); + break; + + case COMMENT: + buffer.append(COMMENTSYM); + buffer.append(element->text); + break; + } + } + else if(param) + { + switch(param->type) + { + case skin_tag_parameter::STRING: + buffer.append(param->data.text); + break; + + case skin_tag_parameter::NUMERIC: + buffer.append(QString::number(param->data.numeric, 10)); + break; + + case skin_tag_parameter::DEFAULT: + buffer.append(DEFAULTSYM); + break; + + } + } else - return element->line; -} -int ParseTreeNode::row() const -{ - if(parentLink) - return parentLink->children.indexOf(const_cast(this)); - return 0; -} + { + for(int i = 0; i < children.count(); i++) + buffer.append(children[i]->genCode()); + } -ParseTreeNode* ParseTreeNode::parent() -{ - return parentLink; + return buffer; } +/* +ParseTreeNode* child(int row); +int numChildren() const; +QVariant data(int column) const; +int getRow() const; +ParseTreeNode* getParent(); +*/ diff --git a/utils/themeeditor/parsetreenode.h b/utils/themeeditor/parsetreenode.h index c3372e0a20..4d8c4ebc14 100644 --- a/utils/themeeditor/parsetreenode.h +++ b/utils/themeeditor/parsetreenode.h @@ -1,3 +1,24 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + #ifndef PARSETREENODE_H #define PARSETREENODE_H @@ -13,24 +34,23 @@ extern "C" class ParseTreeNode { public: - ParseTreeNode(struct skin_element* data, ParseTreeNode* parent, bool tree); - ParseTreeNode(struct skin_tag_parameter* param, ParseTreeNode* parent); - virtual ~ParseTreeNode(); + ParseTreeNode(struct skin_element* data); + ParseTreeNode(struct skin_element* data, ParseTreeNode* parent); + ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent); - void appendChild(ParseTreeNode* child); + QString genCode() const; ParseTreeNode* child(int row); - int childCount() const; - int columnCount() const; + int numChildren() const; QVariant data(int column) const; - int row() const; - ParseTreeNode* parent(); + int getRow() const; + ParseTreeNode* getParent(); private: - ParseTreeNode* parentLink; - QList children; + ParseTreeNode* parent; struct skin_element* element; struct skin_tag_parameter* param; + QList children; }; diff --git a/utils/themeeditor/skin_parser.c b/utils/themeeditor/skin_parser.c index a6c5ea41a2..2f68cdf1c8 100644 --- a/utils/themeeditor/skin_parser.c +++ b/utils/themeeditor/skin_parser.c @@ -103,7 +103,14 @@ struct skin_element* skin_parse(char* document) else to_write = &(last->next); - if(sublines) + if(*cursor == '\n') + { + *to_write = skin_alloc_element(); + skin_parse_newline(*to_write, &cursor); + if(!last) + return NULL; + } + else if(sublines) { *to_write = skin_parse_sublines(&cursor); last = *to_write; @@ -202,23 +209,6 @@ struct skin_element* skin_parse_line_optional(char** document, int conditional) } } - if(*cursor == '\n') - { - /* Allocating memory if necessary */ - if(root) - { - current->next = skin_alloc_element(); - current = current->next; - } - else - { - current = skin_alloc_element(); - root = current; - } - if(!skin_parse_newline(current, &cursor)) - return NULL; - } - /* Moving up the calling function's pointer */ *document = cursor; diff --git a/utils/themeeditor/skin_parser.h b/utils/themeeditor/skin_parser.h index 7de726bbfc..7b3ab13ad0 100644 --- a/utils/themeeditor/skin_parser.h +++ b/utils/themeeditor/skin_parser.h @@ -36,13 +36,13 @@ extern char skin_parse_tree[]; /* Possible types of element in a WPS file */ enum skin_element_type { - TEXT, + LINE, + SUBLINES, + CONDITIONAL, + TAG, NEWLINE, + TEXT, COMMENT, - TAG, - CONDITIONAL, - SUBLINES, - LINE }; enum skin_errorcode -- cgit