/***************************************************************************
UlxrIdlParser.cpp - parse Ulxr idl files
-------------------
begin : Sun May 20 2007
copyright : (C) 2002-2007 by Ewald Arnold
email : ulxmlrpcpp@ewald-arnold.de
$Id: UlxrIdlParser.cpp 1007 2007-07-21 13:54:34Z ewald-arnold $
***************************************************************************/
/**************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
***************************************************************************/
#include "UlxrIdlParser.h"
#include "xmlexcept.h"
/*
Ulxr-IDL : SOURCE
| INCLUDE
| CLASS
;
CLASS : NAME
| LINK_SCOPE
| SUPER
| METHOD
| CONSTRUCTOR
;
METHOD | CONSTRUCTOR : TYPE
| NAME
| ARG
;
ARG : TYPE
| NAME
;
*/
#define TAG_ULXR_IDL "ULXR-IDL"
#define TAG_SOURCE "SOURCE"
#define TAG_INCLUDE "INCLUDE"
#define TAG_CLASS "CLASS"
#define TAG_FUNCTION "FUNCTION"
#define TAG_NAME "NAME"
#define TAG_LINK_SCOPE "LINK_SCOPE"
#define TAG_SUPER "SUPER"
#define TAG_METHOD "METHOD"
#define TAG_CONSTRUCTOR "CONSTRUCTOR"
#define TAG_TYPE "TYPE"
#define TAG_ARG "ARG"
UlxrIdlParser::UlxrIdlParser()
: XmlParser()
{
states.push(new ParserState(eNone));
}
UlxrIdlParser::~UlxrIdlParser()
{
while (states.size() != 0)
{
delete states.top();
states.pop();
}
}
void UlxrIdlParser::startElement(const XML_Char* name, const char** atts)
{
if (!testStartElement(name, atts))
XmlParser::testStartElement(name, atts);
}
bool UlxrIdlParser::testStartElement(const XML_Char* name, const char** atts)
{
AttributeList attributes (this, atts);
switch(states.top()->getParserState() )
{
case eNone:
if(strcmp(name, TAG_ULXR_IDL) == 0)
{
in_arg = false;
in_method = false;
in_function = false;
theClass.setSource("");
functions.clear();
setComplete (false);
states.push(new ParserState(eUlxrIdl));
}
else
return false;
break;
case eUlxrIdl:
if(strcmp(name, TAG_SOURCE) == 0)
states.push(new ParserState(eSource));
else if(strcmp(name, TAG_INCLUDE) == 0)
states.push(new ParserState(eInclude));
else if(strcmp(name, TAG_CLASS) == 0)
{
theClass.clear();
states.push(new ParserState(eClass));
}
else if(strcmp(name, TAG_FUNCTION) == 0)
{
states.push(new ParserState(eFunction));
in_function = true;
method.clear();
method.setFunction(true);
}
else
return false;
break;
case eSuper:
if(strcmp(name, TAG_TYPE) == 0)
states.push(new ParserState(eType));
else
return false;
break;
case eClass:
if(strcmp(name, TAG_NAME) == 0)
states.push(new ParserState(eName));
else if(strcmp(name, TAG_LINK_SCOPE) == 0)
states.push(new ParserState(eLinkScope));
else if(strcmp(name, TAG_SUPER) == 0)
states.push(new ParserState(eSuper));
else if(strcmp(name, TAG_METHOD) == 0)
{
in_method = true;
method.clear();
AttributeList attribs(this, atts);
bool virt = false;
if (attribs.hasAttribute("virtual"))
virt = "1" == attribs.getAttribute("virtual");
bool cons = false;
if (attribs.hasAttribute("qual"))
cons = "const" == attribs.getAttribute("qual");
method.setProperty(false, virt, cons);
states.push(new ParserState(eMethod));
}
else if(strcmp(name, TAG_CONSTRUCTOR) == 0)
{
in_method = true;
method.clear();
AttributeList attribs(this, atts);
bool virt = false;
if (attribs.hasAttribute("virtual"))
virt = "1" == attribs.getAttribute("virtual");
bool cons = false;
if (attribs.hasAttribute("qual"))
cons = "const" == attribs.getAttribute("qual");
method.setProperty(true, virt, cons);
states.push(new ParserState(eConstructor));
}
else
return false;
break;
case eFunction:
case eMethod:
case eConstructor: // fallthrough
if(strcmp(name, TAG_TYPE) == 0)
{
AttributeList attribs(this, atts);
std::string left;
if (attribs.hasAttribute("qleft"))
left = attribs.getAttribute("qleft");
std::string right;
if (attribs.hasAttribute("qright"))
right = attribs.getAttribute("qright");
type.setProperty(left, right);
states.push(new ParserState(eType));
}
else if(strcmp(name, TAG_NAME) == 0)
states.push(new ParserState(eName));
else if(strcmp(name, TAG_ARG) == 0)
{
arg.clear();
in_arg = true;
states.push(new ParserState(eArg));
}
else
return false;
break;
case eArg:
if(strcmp(name, TAG_TYPE) == 0)
{
type.clear();
AttributeList attribs(this, atts);
std::string left;
if (attribs.hasAttribute("qleft"))
left= attribs.getAttribute("qleft");
std::string right;
if (attribs.hasAttribute("qright"))
right = attribs.getAttribute("qright");
type.setProperty(left, right);
states.push(new ParserState(eType));
}
else if(strcmp(name, TAG_NAME) == 0)
states.push(new ParserState(eName));
else
return false;
break;
default:
return false;
}
return true;
}
void UlxrIdlParser::endElement(const XML_Char *name)
{
if (!testEndElement(name))
XmlParser::testEndElement(name);
}
bool UlxrIdlParser::testEndElement(const XML_Char *name)
{
if (states.size() <= 1)
throw XmlException(NotWellformedError,
"Problem while parsing xml structure",
getCurrentLineNumber(),
std::string("abnormal program behaviour: UlxrIdlParser::testEndElement() had no states left: "));
ParserState *curr = states.top();
states.pop();
switch(curr->getParserState() )
{
case eUlxrIdl:
setComplete(true);
assertEndElement(name, TAG_ULXR_IDL);
break;
case eSource:
assertEndElement(name, TAG_SOURCE);
theClass.setSource(curr->getCharData());
method.setSource(curr->getCharData());
break;
case eInclude:
assertEndElement(name, TAG_INCLUDE);
break;
case eClass:
assertEndElement(name, TAG_CLASS);
classList.push_back(theClass);
break;
case eName:
assertEndElement(name, TAG_NAME);
if (in_arg)
arg.setName(curr->getCharData());
else if (in_method || in_function)
method.setName(theClass.getName(), curr->getCharData());
else
theClass.setName(curr->getCharData());
break;
case eLinkScope:
assertEndElement(name, TAG_LINK_SCOPE);
break;
case eSuper:
assertEndElement(name, TAG_SUPER);
break;
case eFunction:
assertEndElement(name, TAG_FUNCTION);
functions.push_back(method);
in_function = false;
break;
case eMethod:
assertEndElement(name, TAG_METHOD);
theClass.addMethod(method);
in_method = false;
break;
case eConstructor:
assertEndElement(name, TAG_CONSTRUCTOR);
theClass.addMethod(method);
in_method = false;
break;
case eType:
assertEndElement(name, TAG_TYPE);
type.setName(curr->getCharData());
if (in_arg)
arg.setType(type);
else if (in_method || in_function)
method.setType(type);
// else eSuper
break;
case eArg:
assertEndElement(name, TAG_ARG);
in_arg = false;
method.addArgument(arg);
break;
default:
states.push(curr); // put back, someone else will process
return false;
}
delete curr;
return true;
}
unsigned UlxrIdlParser::numClasses() const
{
return classList.size();
}
std::vector<Method> UlxrIdlParser::getFunctions() const
{
return functions;
}
UlxrIdlClass UlxrIdlParser::getClass(unsigned i) const
{
return classList[i];
}
syntax highlighted by Code2HTML, v. 0.9.1