1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Robert Bieber 2010-05-29 00:04:04 +00:00
parent 1dcc21d846
commit 6980c1e998
7 changed files with 257 additions and 103 deletions

View file

@ -27,6 +27,7 @@ extern "C"
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <iostream>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QTreeView> #include <QTreeView>
@ -36,15 +37,21 @@ extern "C"
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
char doc[] = "%Vd(U);Hey\n%?bl(test,3,5,2,1)<param2|param3>"; char doc[] = "#Comment\n%Vd(U);Hey\n%?bl(test,3,5,2,1)<param2|param3>";
struct skin_element* test = skin_parse(doc); 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); QApplication app(argc, argv);
QTreeView tree; QTreeView tree;
@ -53,7 +60,7 @@ int main(int argc, char* argv[])
tree.show(); tree.show();
return app.exec(); return app.exec();
*/
return 0; return 0;
} }

View file

@ -26,8 +26,8 @@
ParseTreeModel::ParseTreeModel(char* wps, QObject* parent): ParseTreeModel::ParseTreeModel(char* wps, QObject* parent):
QAbstractItemModel(parent) QAbstractItemModel(parent)
{ {
this->wps = skin_parse(wps); this->tree = skin_parse(wps);
this->root = new ParseTreeNode(this->wps, 0, true); this->root = new ParseTreeNode(tree, 0);
} }
@ -36,6 +36,12 @@ ParseTreeModel::~ParseTreeModel()
delete root; delete root;
} }
QString genCode()
{
return QString();
}
/*
QModelIndex ParseTreeModel::index(int row, int column, QModelIndex ParseTreeModel::index(int row, int column,
const QModelIndex& parent) const const QModelIndex& parent) const
{ {
@ -98,3 +104,4 @@ QVariant ParseTreeModel::data(const QModelIndex &index, int role) const
ParseTreeNode* item = static_cast<ParseTreeNode*>(index.internalPointer()); ParseTreeNode* item = static_cast<ParseTreeNode*>(index.internalPointer());
return item->data(index.column()); return item->data(index.column());
} }
*/

View file

@ -43,15 +43,19 @@ public:
ParseTreeModel(char* wps, QObject* parent = 0); ParseTreeModel(char* wps, QObject* parent = 0);
virtual ~ParseTreeModel(); virtual ~ParseTreeModel();
QString genCode();
/*
QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex index(int row, int column, const QModelIndex& parent) const;
QModelIndex parent(const QModelIndex &child) const; QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const; QVariant data(const QModelIndex &index, int role) const;
*/
private: private:
ParseTreeNode* root; ParseTreeNode* root;
struct skin_element* wps; struct skin_element* tree;
}; };

View file

@ -1,74 +1,200 @@
/***************************************************************************
* __________ __ ___.
* 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.
*
****************************************************************************/
extern "C"
{
#include "symbols.h"
}
#include "parsetreenode.h" #include "parsetreenode.h"
ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent, /* Root element constructor */
bool tree) ParseTreeNode::ParseTreeNode(struct skin_element* data)
: parent(0), element(0), param(0), children()
{ {
while(data)
if(tree)
{ {
while(data) children.append(new ParseTreeNode(data, this));
data = data->next;
}
}
/* 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++)
{ {
appendChild(new ParseTreeNode(data, this, false)); if(element->params[i].type == skin_tag_parameter::CODE)
data = data->next; 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;
case LINE:
for(struct skin_element* current = data->children[0]; current;
current = current->next)
{
children.append(new ParseTreeNode(current, this));
}
break;
default:
break;
}
}
/* Parameter constructor */
ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent)
: parent(parent), element(0), param(data), children()
{
}
QString ParseTreeNode::genCode() const
{
QString buffer = "";
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;
} }
parentLink = 0;
} }
else else
{ {
element = data; for(int i = 0; i < children.count(); i++)
parentLink = parent; buffer.append(children[i]->genCode());
} }
return buffer;
} }
/*
ParseTreeNode::ParseTreeNode(struct skin_tag_parameter* param, ParseTreeNode* child(int row);
ParseTreeNode* parent) int numChildren() const;
:parentLink(parent), element(0), param(param) QVariant data(int column) const;
{ int getRow() const;
ParseTreeNode* getParent();
} */
ParseTreeNode::~ParseTreeNode()
{
qDeleteAll(children);
}
void ParseTreeNode::appendChild(ParseTreeNode* child)
{
children.append(child);
}
ParseTreeNode* ParseTreeNode::child(int row)
{
return children[row];
}
int ParseTreeNode::childCount() const
{
return children.count();
}
int ParseTreeNode::columnCount() const
{
return 2;
}
QVariant ParseTreeNode::data(int column) const
{
if(column == 0)
return element->type;
else
return element->line;
}
int ParseTreeNode::row() const
{
if(parentLink)
return parentLink->children.indexOf(const_cast<ParseTreeNode*>(this));
return 0;
}
ParseTreeNode* ParseTreeNode::parent()
{
return parentLink;
}

View file

@ -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 #ifndef PARSETREENODE_H
#define PARSETREENODE_H #define PARSETREENODE_H
@ -13,24 +34,23 @@ extern "C"
class ParseTreeNode class ParseTreeNode
{ {
public: public:
ParseTreeNode(struct skin_element* data, ParseTreeNode* parent, bool tree); ParseTreeNode(struct skin_element* data);
ParseTreeNode(struct skin_tag_parameter* param, ParseTreeNode* parent); ParseTreeNode(struct skin_element* data, ParseTreeNode* parent);
virtual ~ParseTreeNode(); ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent);
void appendChild(ParseTreeNode* child); QString genCode() const;
ParseTreeNode* child(int row); ParseTreeNode* child(int row);
int childCount() const; int numChildren() const;
int columnCount() const;
QVariant data(int column) const; QVariant data(int column) const;
int row() const; int getRow() const;
ParseTreeNode* parent(); ParseTreeNode* getParent();
private: private:
ParseTreeNode* parentLink; ParseTreeNode* parent;
QList<ParseTreeNode*> children;
struct skin_element* element; struct skin_element* element;
struct skin_tag_parameter* param; struct skin_tag_parameter* param;
QList<ParseTreeNode*> children;
}; };

View file

@ -103,7 +103,14 @@ struct skin_element* skin_parse(char* document)
else else
to_write = &(last->next); 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); *to_write = skin_parse_sublines(&cursor);
last = *to_write; 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 */ /* Moving up the calling function's pointer */
*document = cursor; *document = cursor;

View file

@ -36,13 +36,13 @@ extern char skin_parse_tree[];
/* Possible types of element in a WPS file */ /* Possible types of element in a WPS file */
enum skin_element_type enum skin_element_type
{ {
TEXT, LINE,
NEWLINE,
COMMENT,
TAG,
CONDITIONAL,
SUBLINES, SUBLINES,
LINE CONDITIONAL,
TAG,
NEWLINE,
TEXT,
COMMENT,
}; };
enum skin_errorcode enum skin_errorcode