#ifndef LLVM_SUPPORT_JSON_PARSER_H
#define LLVM_SUPPORT_JSON_PARSER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
namespace llvm {
class JSONContainer;
class JSONString;
class JSONValue;
class JSONKeyValuePair;
class JSONAtom {
public:
enum Kind { JK_KeyValuePair, JK_Array, JK_Object, JK_String };
Kind getKind() const { return MyKind; }
static bool classof(const JSONAtom *Atom) { return true; }
protected:
JSONAtom(Kind MyKind) : MyKind(MyKind) {}
private:
Kind MyKind;
};
class JSONParser {
public:
JSONParser(StringRef Input, SourceMgr *SM);
JSONValue *parseRoot();
bool validate();
bool failed() const;
private:
JSONString *parseString();
JSONValue *parseValue();
JSONKeyValuePair *parseKeyValuePair();
const JSONAtom *parseElement(JSONAtom::Kind ContainerKind);
StringRef::iterator parseFirstElement(JSONAtom::Kind ContainerKind,
char StartChar, char EndChar,
const JSONAtom *&Element);
StringRef::iterator parseNextElement(JSONAtom::Kind ContainerKind,
char EndChar,
const JSONAtom *&Element);
void nextNonWhitespace();
bool isWhitespace();
void setExpectedError(StringRef Expected, StringRef Found);
void setExpectedError(StringRef Expected, char Found);
bool errorIfAtEndOfFile(StringRef Message);
bool errorIfNotAt(char C, StringRef Message);
bool skipContainer(const JSONContainer &Container);
bool skip(const JSONAtom &Atom);
BumpPtrAllocator ValueAllocator;
MemoryBuffer *InputBuffer;
SourceMgr *SM;
StringRef::iterator Position;
StringRef::iterator End;
bool Failed;
friend class JSONContainer;
};
class JSONValue : public JSONAtom {
protected:
JSONValue(Kind MyKind) : JSONAtom(MyKind) {}
public:
static bool classof(const JSONAtom *Atom) {
switch (Atom->getKind()) {
case JK_Array:
case JK_Object:
case JK_String:
return true;
case JK_KeyValuePair:
return false;
}
llvm_unreachable("Invalid JSONAtom kind");
}
static bool classof(const JSONValue *Value) { return true; }
};
class JSONString : public JSONValue {
public:
StringRef getRawText() const { return RawText; }
private:
JSONString(StringRef RawText) : JSONValue(JK_String), RawText(RawText) {}
StringRef RawText;
friend class JSONParser;
public:
static bool classof(const JSONAtom *Atom) {
return Atom->getKind() == JK_String;
}
static bool classof(const JSONString *String) { return true; }
};
class JSONKeyValuePair : public JSONAtom {
public:
const JSONString * const Key;
const JSONValue * const Value;
private:
JSONKeyValuePair(const JSONString *Key, const JSONValue *Value)
: JSONAtom(JK_KeyValuePair), Key(Key), Value(Value) {}
friend class JSONParser;
public:
static bool classof(const JSONAtom *Atom) {
return Atom->getKind() == JK_KeyValuePair;
}
static bool classof(const JSONKeyValuePair *KeyValuePair) { return true; }
};
class JSONContainer : public JSONValue {
private:
class AtomIterator {
public:
AtomIterator(const AtomIterator &I) : Container(I.Container) {}
bool operator==(const AtomIterator &I) const {
if (isEnd() || I.isEnd())
return isEnd() == I.isEnd();
return Container->Position == I.Container->Position;
}
bool operator!=(const AtomIterator &I) const {
return !(*this == I);
}
AtomIterator &operator++() {
Container->parseNextElement();
return *this;
}
const JSONAtom *operator*() {
return Container->Current;
}
private:
AtomIterator() : Container(0) {}
AtomIterator(const JSONContainer *Container) : Container(Container) {}
bool isEnd() const {
return Container == 0 || Container->Position == StringRef::iterator();
}
const JSONContainer * const Container;
friend class JSONContainer;
};
protected:
template <typename AtomT>
class IteratorTemplate : public std::iterator<std::forward_iterator_tag,
const AtomT*> {
public:
explicit IteratorTemplate(const AtomIterator& AtomI)
: AtomI(AtomI) {}
bool operator==(const IteratorTemplate &I) const {
return AtomI == I.AtomI;
}
bool operator!=(const IteratorTemplate &I) const { return !(*this == I); }
IteratorTemplate &operator++() {
++AtomI;
return *this;
}
const AtomT *operator*() { return dyn_cast<AtomT>(*AtomI); }
private:
AtomIterator AtomI;
};
JSONContainer(JSONParser *Parser, char StartChar, char EndChar,
JSONAtom::Kind ContainerKind)
: JSONValue(ContainerKind), Parser(Parser),
Position(), Current(0), Started(false),
StartChar(StartChar), EndChar(EndChar) {}
AtomIterator atom_begin() const {
if (Started)
report_fatal_error("Cannot parse container twice.");
Started = true;
Position = Parser->parseFirstElement(getKind(), StartChar, EndChar, Current);
return AtomIterator(this);
}
AtomIterator atom_end() const {
return AtomIterator();
}
private:
AtomIterator atom_current() const {
if (!Started)
return atom_begin();
return AtomIterator(this);
}
void parseNextElement() const {
Parser->skip(*Current);
Position = Parser->parseNextElement(getKind(), EndChar, Current);
}
JSONParser * const Parser;
mutable StringRef::iterator Position;
mutable const JSONAtom *Current;
mutable bool Started;
const char StartChar;
const char EndChar;
friend class JSONParser;
public:
static bool classof(const JSONAtom *Atom) {
switch (Atom->getKind()) {
case JK_Array:
case JK_Object:
return true;
case JK_KeyValuePair:
case JK_String:
return false;
}
llvm_unreachable("Invalid JSONAtom kind");
}
static bool classof(const JSONContainer *Container) { return true; }
};
class JSONArray : public JSONContainer {
public:
typedef IteratorTemplate<JSONValue> const_iterator;
const_iterator begin() const { return const_iterator(atom_begin()); }
const_iterator end() const { return const_iterator(atom_end()); }
private:
JSONArray(JSONParser *Parser)
: JSONContainer(Parser, '[', ']', JSONAtom::JK_Array) {}
public:
static bool classof(const JSONAtom *Atom) {
return Atom->getKind() == JSONAtom::JK_Array;
}
static bool classof(const JSONArray *Array) { return true; }
friend class JSONParser;
};
class JSONObject : public JSONContainer {
public:
typedef IteratorTemplate<JSONKeyValuePair> const_iterator;
const_iterator begin() const { return const_iterator(atom_begin()); }
const_iterator end() const { return const_iterator(atom_end()); }
private:
JSONObject(JSONParser *Parser)
: JSONContainer(Parser, '{', '}', JSONAtom::JK_Object) {}
public:
static bool classof(const JSONAtom *Atom) {
return Atom->getKind() == JSONAtom::JK_Object;
}
static bool classof(const JSONObject *Object) { return true; }
friend class JSONParser;
};
}
#endif // LLVM_SUPPORT_JSON_PARSER_H