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:
parent
1dcc21d846
commit
6980c1e998
7 changed files with 257 additions and 103 deletions
|
|
@ -27,6 +27,7 @@ extern "C"
|
|||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QTreeView>
|
||||
|
|
@ -36,15 +37,21 @@ extern "C"
|
|||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/*
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QTreeView tree;
|
||||
|
|
@ -53,7 +60,7 @@ int main(int argc, char* argv[])
|
|||
tree.show();
|
||||
|
||||
return app.exec();
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ParseTreeNode*>(index.internalPointer());
|
||||
return item->data(index.column());
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent,
|
||||
bool tree)
|
||||
/* Root element constructor */
|
||||
ParseTreeNode::ParseTreeNode(struct skin_element* data)
|
||||
: parent(0), element(0), param(0), children()
|
||||
{
|
||||
|
||||
if(tree)
|
||||
while(data)
|
||||
{
|
||||
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));
|
||||
data = data->next;
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
element = data;
|
||||
parentLink = parent;
|
||||
for(int i = 0; i < children.count(); i++)
|
||||
buffer.append(children[i]->genCode());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ParseTreeNode::ParseTreeNode(struct skin_tag_parameter* param,
|
||||
ParseTreeNode* parent)
|
||||
:parentLink(parent), element(0), param(param)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
ParseTreeNode* child(int row);
|
||||
int numChildren() const;
|
||||
QVariant data(int column) const;
|
||||
int getRow() const;
|
||||
ParseTreeNode* getParent();
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<ParseTreeNode*> children;
|
||||
ParseTreeNode* parent;
|
||||
struct skin_element* element;
|
||||
struct skin_tag_parameter* param;
|
||||
QList<ParseTreeNode*> children;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@ extern char skin_parse_tree[];
|
|||
/* Possible types of element in a WPS file */
|
||||
enum skin_element_type
|
||||
{
|
||||
TEXT,
|
||||
NEWLINE,
|
||||
COMMENT,
|
||||
TAG,
|
||||
CONDITIONAL,
|
||||
LINE,
|
||||
SUBLINES,
|
||||
LINE
|
||||
CONDITIONAL,
|
||||
TAG,
|
||||
NEWLINE,
|
||||
TEXT,
|
||||
COMMENT,
|
||||
};
|
||||
|
||||
enum skin_errorcode
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue