2000-10-18 23:37:44 +00:00
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "parser.h"
|
|
|
|
#include "world.h"
|
|
|
|
#include "xmlparser.h"
|
|
|
|
|
|
|
|
namespace JavaScript {
|
|
|
|
|
|
|
|
|
2000-10-18 23:55:47 +00:00
|
|
|
bool XMLTag::getValue(String &name, String **value)
|
2000-10-18 23:37:44 +00:00
|
|
|
{
|
|
|
|
AttributeList::iterator i = mAttributeList.find(name);
|
|
|
|
if (i == mAttributeList.end())
|
|
|
|
return false;
|
|
|
|
else {
|
2000-10-18 23:55:47 +00:00
|
|
|
*value = &i->second;
|
2000-10-18 23:37:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void XMLParser::syntaxError(const char *msg, uint backUp)
|
|
|
|
{
|
|
|
|
mReader.unget(backUp);
|
|
|
|
mReader.error(Exception::syntaxError, widenCString(msg), mReader.getPos());
|
|
|
|
}
|
|
|
|
|
|
|
|
void XMLParser::parseName(String &id)
|
|
|
|
{
|
|
|
|
char16 ch = mReader.peek();
|
|
|
|
CharInfo chi(ch);
|
|
|
|
if (isAlpha(chi)) {
|
|
|
|
mReader.beginRecording(id);
|
|
|
|
mReader.recordChar(mReader.get());
|
|
|
|
while (true) {
|
|
|
|
ch = mReader.peek();
|
|
|
|
CharInfo chi(ch);
|
|
|
|
if (isAlphanumeric(chi))
|
|
|
|
mReader.recordChar(mReader.get());
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mReader.endRecording();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
syntaxError("Invalid name");
|
|
|
|
}
|
|
|
|
|
|
|
|
void XMLParser::parseWhiteSpace()
|
|
|
|
{
|
|
|
|
char16 ch = mReader.peek();
|
|
|
|
CharInfo chi(ch);
|
|
|
|
while (isSpace(chi)) {
|
|
|
|
ch = mReader.get();
|
|
|
|
if (isLineBreak(ch))
|
|
|
|
mReader.beginLine();
|
|
|
|
chi = CharInfo(mReader.peek());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void XMLParser::parseAttrValue(String &val)
|
|
|
|
{
|
|
|
|
char16 ch = mReader.get();
|
|
|
|
if (ch != '\"')
|
|
|
|
syntaxError("'\"' expected");
|
|
|
|
else {
|
|
|
|
mReader.beginRecording(val);
|
|
|
|
while (true) {
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated value");
|
|
|
|
if (ch == '\"')
|
|
|
|
break;
|
|
|
|
mReader.recordChar(ch);
|
|
|
|
}
|
|
|
|
mReader.endRecording();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XMLTag *XMLParser::parseTag()
|
|
|
|
{
|
|
|
|
char16 ch;
|
|
|
|
XMLTag *tag = new XMLTag();
|
|
|
|
ch = mReader.peek();
|
|
|
|
if (ch == '/') {
|
|
|
|
tag->setEndTag();
|
|
|
|
mReader.get();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (ch == '!') {
|
|
|
|
mReader.get();
|
|
|
|
if (mReader.peek() != '-')
|
|
|
|
syntaxError("badly formed tag");
|
|
|
|
mReader.get();
|
|
|
|
if (mReader.peek() != '-')
|
|
|
|
syntaxError("badly formed tag");
|
|
|
|
mReader.get();
|
|
|
|
while (true) {
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated comment tag");
|
|
|
|
if (ch == '-') {
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated comment tag");
|
|
|
|
if (ch != '-')
|
|
|
|
mReader.unget();
|
|
|
|
else {
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated comment tag");
|
|
|
|
if (ch != '>')
|
|
|
|
syntaxError("encountered '--' in comment");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isLineBreak(ch))
|
|
|
|
mReader.beginLine();
|
|
|
|
}
|
|
|
|
tag->setComment();
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
parseName(tag->name());
|
|
|
|
parseWhiteSpace();
|
|
|
|
CharInfo chi(mReader.peek());
|
|
|
|
while (isAlpha(chi)) {
|
|
|
|
String attrValue;
|
|
|
|
String attrName;
|
|
|
|
parseName(attrName);
|
|
|
|
if (mReader.peek() == '=') {
|
|
|
|
mReader.get();
|
|
|
|
parseAttrValue(attrValue);
|
|
|
|
}
|
|
|
|
tag->addAttribute(attrName, attrValue);
|
|
|
|
parseWhiteSpace();
|
|
|
|
chi = CharInfo(mReader.peek());
|
|
|
|
}
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated tag");
|
|
|
|
if (ch == '/') {
|
|
|
|
tag->setEmpty();
|
|
|
|
ch = mReader.get();
|
|
|
|
}
|
|
|
|
if (ch != '>')
|
|
|
|
syntaxError("'>' expected");
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void XMLParser::parseTagBody(XMLNode *parent, XMLTag *startTag)
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
char16 ch = mReader.get();
|
|
|
|
while (ch != '<') {
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
syntaxError("Unterminated tag body");
|
|
|
|
parent->addToBody(ch);
|
|
|
|
ch = mReader.get();
|
|
|
|
}
|
|
|
|
XMLTag *tag = parseTag();
|
|
|
|
if (tag->isEndTag() && (tag->name().compare(startTag->name()) == 0))
|
|
|
|
break;
|
|
|
|
else {
|
|
|
|
XMLNode *child = new XMLNode(parent, tag);
|
|
|
|
if (!tag->isEmpty())
|
|
|
|
parseTagBody(child, tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XMLNode *XMLParser::parseDocument()
|
|
|
|
{
|
|
|
|
XMLNode *top = new XMLNode(NULL, new XMLTag(widenCString("TOP")));
|
|
|
|
char16 ch = mReader.get();
|
|
|
|
while (ch == '<') {
|
|
|
|
XMLTag *tag = parseTag();
|
|
|
|
XMLNode *n = new XMLNode(top, tag);
|
|
|
|
if (!tag->isEmpty()) {
|
|
|
|
parseTagBody(n, tag);
|
|
|
|
}
|
|
|
|
parseWhiteSpace();
|
|
|
|
ch = mReader.get();
|
|
|
|
if (mReader.getEof(ch))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return top;
|
|
|
|
}
|
|
|
|
|
|
|
|
Formatter& operator<<(Formatter& f, const XMLTag& tag)
|
|
|
|
{
|
|
|
|
tag.print(f);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
Formatter& operator<<(Formatter& f, const XMLNode& node)
|
|
|
|
{
|
|
|
|
node.print(f);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace JavaScript */
|