зеркало из https://github.com/mozilla/gecko-dev.git
173 строки
4.8 KiB
C++
173 строки
4.8 KiB
C++
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include <map>
|
|
|
|
#include "parser.h"
|
|
#include "world.h"
|
|
|
|
|
|
namespace JavaScript {
|
|
|
|
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag, CDataTag } TagFlag;
|
|
|
|
|
|
class XMLLexer
|
|
{
|
|
public:
|
|
XMLLexer(const char *filename);
|
|
~XMLLexer() { if (base) delete base; }
|
|
|
|
char get() { if (p != end) return *p++; else return '\0'; }
|
|
void skip(uint32 n) { p += n; ASSERT(p <= end); }
|
|
char peek() { return *p; }
|
|
void unget(uint32 n = 1) { p -=n; ASSERT(p >= base); }
|
|
bool getEof() { return (p == end); }
|
|
bool hasAvailable(uint32 n) { return (uint32)(end - p) >= n; }
|
|
bool match(const char *s, uint32 n) { return hasAvailable(n) && (strstr(p, s) == p); }
|
|
bool match(const char *s) { return match(s, strlen(s)); }
|
|
|
|
uint32 getPos() { return uint32(p - base); }
|
|
|
|
void beginRecording(String &s);
|
|
String &endRecording();
|
|
void recordChar(char c);
|
|
|
|
void beginLine() { }
|
|
|
|
char *base;
|
|
char *p;
|
|
char *end;
|
|
|
|
char *recordPos;
|
|
char *recordBase;
|
|
String *recordString;
|
|
|
|
bool isAlpha(char c) { return JavaScript::isAlpha(CharInfo(c)); }
|
|
bool isAlphanumeric(char c) { return JavaScript::isAlphanumeric(CharInfo(c)); }
|
|
bool isSpace(char c) { return JavaScript::isSpace(CharInfo(c)); }
|
|
bool isLineBreak(char c) { return JavaScript::isLineBreak(CharInfo(c)); }
|
|
|
|
};
|
|
|
|
|
|
class XMLNode;
|
|
typedef std::vector<XMLNode *> XMLNodeList;
|
|
typedef std::multimap<String, String, std::less<String> > AttributeList;
|
|
typedef AttributeList::value_type AttributeValue;
|
|
|
|
class XMLTag {
|
|
public:
|
|
XMLTag() : mFlag(Tag) { }
|
|
XMLTag(String name) : mName(name), mFlag(Tag) { }
|
|
|
|
void addAttribute(const String &name, const String &value) { mAttributeList.insert(AttributeValue(name, value) ); }
|
|
bool getValue(const String &name, String &value); // returns the value of the most newly inserted attribute 'name'.
|
|
bool hasAttribute(const String &name) { return (mAttributeList.find(name) != mAttributeList.end()); }
|
|
|
|
String &name() { return mName; }
|
|
|
|
void setTag(TagFlag f) { mFlag = f; }
|
|
|
|
bool isEmpty() const { return mFlag == EmptyTag; }
|
|
bool isEndTag() const { return mFlag == EndTag; }
|
|
bool isComment() const { return mFlag == CommentTag; }
|
|
|
|
bool hasContent() const { return mFlag == Tag; }
|
|
|
|
String mName;
|
|
TagFlag mFlag;
|
|
AttributeList mAttributeList;
|
|
|
|
void print(Formatter& f) const
|
|
{
|
|
if (isComment())
|
|
f << "XML Comment tag\n";
|
|
else
|
|
f << "XMLTag '" << mName << "'\n";
|
|
for (AttributeList::const_iterator i = mAttributeList.begin(); i != mAttributeList.end(); i++) {
|
|
f << "\t'" << i->first << "' = '" << i->second << "'\n";
|
|
}
|
|
}
|
|
};
|
|
|
|
Formatter& operator<<(Formatter& f, const XMLTag& tag);
|
|
Formatter& operator<<(Formatter& f, const XMLNode& node);
|
|
|
|
class XMLNode
|
|
{
|
|
public:
|
|
XMLNode(XMLNode *parent, XMLTag *tag) : mParent(parent), mTag(tag) { if (parent) parent->addChild(this); }
|
|
|
|
String &name() { return mTag->name(); }
|
|
XMLTag *tag() { return mTag; }
|
|
|
|
String &body() { return mBody; }
|
|
|
|
void addToBody(String contents) { mBody += contents; }
|
|
void addToBody(char16 ch) { mBody += ch; }
|
|
|
|
void addChild(XMLNode *child) { mChildren.push_back(child); }
|
|
XMLNodeList &children() { return mChildren; }
|
|
|
|
bool getValue(const String &name, String &value)
|
|
{ return mTag->getValue(name, value); }
|
|
bool hasAttribute(const String &name) { return mTag->hasAttribute(name); }
|
|
|
|
|
|
void print(Formatter& f) const
|
|
{
|
|
f << *mTag;
|
|
if (mParent)
|
|
f << "parent = '" << mParent->name() << "'";
|
|
else
|
|
f << "parent = NULL";
|
|
|
|
XMLNodeList::const_iterator i = mChildren.begin();
|
|
XMLNodeList::const_iterator end = mChildren.end();
|
|
if (i != end) {
|
|
f << "\nChildren :\n";
|
|
while (i != end) {
|
|
f << **i;
|
|
f << "\n";
|
|
i++;
|
|
}
|
|
}
|
|
f << "\n";
|
|
}
|
|
|
|
XMLNodeList mChildren;
|
|
XMLNode *mParent;
|
|
XMLTag *mTag;
|
|
String mBody;
|
|
};
|
|
|
|
|
|
|
|
class XMLParser {
|
|
public:
|
|
void syntaxError(const char *message, uint backUp = 1);
|
|
char16 doEscape();
|
|
|
|
XMLParser(const char *fileName) : mReader(fileName) { }
|
|
|
|
void parseStringLiteral(String &val);
|
|
|
|
void parseName(String &id);
|
|
void parseWhiteSpace();
|
|
void parseAttrValue(String &val);
|
|
XMLTag *parseTag();
|
|
void parseTagBody(XMLNode *parent, XMLTag *startTag);
|
|
XMLNode *parseDocument();
|
|
|
|
|
|
XMLLexer mReader;
|
|
|
|
};
|
|
|
|
|
|
|
|
} /* namespace JavaScript */
|