std::memcpy(object, literal.GetString().c_str(), literal.GetString().size());
object[literal.GetString().size()] = '\0';
break;
+ case Literal::SCRIPT:
+ throw Error("script compiler not implemented");
case Literal::STRING:
std::memcpy(object, literal.GetString().c_str(), literal.GetString().size());
object[literal.GetString().size()] = '\0';
break;
case Literal::OBJECT:
throw Error("illogical branch: read literal object as non-object literal");
- break;
}
}
values[typeId].push_back(str);
}
break;
+ case Literal::SCRIPT:
+ throw Error("script compiler not implemented");
case Literal::STRING:
{
typeId = TypeDescription::GetTypeId("String");
}
+Literal::Literal(const vector<ScriptToken *> &s)
+: props(0)
+, script(s)
+, i1(0), i2(0)
+, i3(0), i4(0)
+, b(false)
+, type(SCRIPT) {
+
+}
+
Literal::~Literal() {
switch (type) {
case ARRAY_VALUES:
case OBJECT:
delete props;
break;
+ case SCRIPT:
+ for (vector<ScriptToken *>::const_iterator i(script.begin()), end(script.end()); i != end; ++i) {
+ delete *i;
+ }
+ break;
default:
break;
}
}
}
+const vector<ScriptToken *> &Literal::GetScript() const {
+ if (type == SCRIPT) {
+ return script;
+ } else {
+ throw runtime_error("tried to access script of non-script literal");
+ }
+}
+
Value::~Value() {
if (isLiteral) {
}
}
+
+ScriptToken::ScriptToken(const string &s, Type t)
+: literal(0)
+, str(s)
+, type(t) {
+ if (type == LITERAL) {
+ throw runtime_error("cannot create script literal without literal");
+ }
+}
+
+ScriptToken::ScriptToken(Literal *l)
+: literal(l)
+, str()
+, type(LITERAL) {
+ if (!literal) {
+ throw runtime_error("cannot create script literal without literal");
+ }
+}
+
+ScriptToken::~ScriptToken() {
+ delete literal;
+}
+
+const string &ScriptToken::RegisterName() const {
+ if (type == REGISTER) {
+ return str;
+ } else {
+ throw runtime_error("access to register name of non-register script token");
+ }
+}
+
+const string &ScriptToken::CommandName() const {
+ if (type == COMMAND) {
+ return str;
+ } else {
+ throw runtime_error("access to command name of non-command script token");
+ }
+}
+
+const string &ScriptToken::GetIdentifier() const {
+ if (type == IDENTIFIER) {
+ return str;
+ } else {
+ throw runtime_error("access to identifier of non-identifier script token");
+ }
+}
+
+const Literal *ScriptToken::GetLiteral() const {
+ if (type == LITERAL) {
+ return literal;
+ } else {
+ throw runtime_error("access to literal value of non-literal script token");
+ }
+}
+
}
case loader::Literal::OBJECT:
out << "object of type " << l.GetTypeName();
break;
+ case loader::Literal::SCRIPT:
+ out << "script";
+ break;
}
return out;
}
namespace loader {
+class ScriptToken {
+
+public:
+ enum Type {
+ COMMAND,
+ REGISTER,
+ IDENTIFIER,
+ LITERAL,
+ };
+
+ ScriptToken(const std::string &, Type);
+ explicit ScriptToken(Literal *);
+ ~ScriptToken();
+private:
+ ScriptToken(const ScriptToken &);
+ ScriptToken &operator =(const ScriptToken &);
+
+public:
+ Type GetType() const { return type; }
+ const std::string &RegisterName() const;
+ const std::string &CommandName() const;
+ const std::string &GetIdentifier() const;
+ const Literal *GetLiteral() const;
+
+private:
+ Literal *literal;
+ std::string str;
+ Type type;
+
+};
+
+
class Literal {
public:
PATH,
STRING,
VECTOR,
- OBJECT
+ OBJECT,
+ SCRIPT,
};
public:
Literal(const std::string &);
Literal(int x, int y);
Literal(const std::string &typeName, PropertyList *properties);
+ explicit Literal(const std::vector<ScriptToken *> &);
~Literal();
private:
Literal(const Literal &);
int GetY() const;
const std::string &GetTypeName() const;
const PropertyList *GetProperties() const;
+ const std::vector<ScriptToken *> &GetScript() const;
private:
PropertyList *props;
std::string typeName, str;
std::vector<Value *> values;
std::vector<PropertyList *> propertyLists;
+ std::vector<ScriptToken *> script;
int i1, i2, i3, i4;
bool b;
Type type;
case Tokenizer::Token::BRACKET_OPEN:
case Tokenizer::Token::PARENTHESIS_OPEN:
case Tokenizer::Token::NUMBER:
+ case Tokenizer::Token::SCRIPT_BEGIN:
case Tokenizer::Token::STRING:
case Tokenizer::Token::KEYWORD_FALSE:
case Tokenizer::Token::KEYWORD_TRUE:
return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
}
+bool Parser::BeginningOfScriptLiteral(const Tokenizer::Token &t) const {
+ return t.type == Tokenizer::Token::SCRIPT_BEGIN;
+}
+
Definition *Parser::ParseDefinition() {
string typeName(ParseTypeName());
string identifier(ParseIdentifier());
if (t.type == Tokenizer::Token::TYPE_NAME) {
PropertyList *props(ParsePropertyList());
return new Literal(t.str, props);
- } else if (BeginningOfLiteral(t)) {
+ } else if (BeginningOfScriptLiteral(t)) {
+ tok.Putback(t);
+ return ParseScript();
+ } else if (BeginningOfPrimitiveLiteral(t)) {
switch (t.type) {
case Tokenizer::Token::CHEVRON_OPEN:
tok.Putback(t);
return new Literal(x.number, y.number);
}
+Literal *Parser::ParseScript() {
+ std::string msg("error parsing script");
+ Tokenizer::Token t(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::SCRIPT_BEGIN, msg);
+
+ vector<ScriptToken *> script;
+ try {
+ while (t.type != Tokenizer::Token::SCRIPT_END) {
+ if (BeginningOfPrimitiveLiteral(t)) {
+ tok.Putback(t);
+ script.push_back(new ScriptToken(ParseLiteral()));
+ } else {
+ switch (t.type) {
+ case Tokenizer::Token::COMMAND: {
+ Tokenizer::Token t2(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER, msg);
+ script.push_back(new ScriptToken(t2.str, ScriptToken::COMMAND));
+ break;
+ }
+ case Tokenizer::Token::IDENTIFIER: {
+ script.push_back(new ScriptToken(t.str, ScriptToken::IDENTIFIER));
+ break;
+ }
+ case Tokenizer::Token::REGISTER: {
+ Tokenizer::Token t2(GetToken());
+ AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER, msg);
+ script.push_back(new ScriptToken(t2.str, ScriptToken::REGISTER));
+ break;
+ }
+ default:
+ throw Error(file, tok.Line(), string("unexpected token in script: ") + TokenTypeToString(t.type));
+ }
+ }
+ t = GetToken();
+ }
+ } catch (...) {
+ for (vector<ScriptToken *>::const_iterator i(script.begin()), end(script.end()); i != end; ++i) {
+ delete *i;
+ }
+ throw;
+ }
+ return new Literal(script);
+}
+
+
void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
if (expected != actual) {
throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
Literal *ParseArray();
Literal *ParseColor();
Literal *ParseVector();
+ Literal *ParseScript();
private:
void AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected);
bool BeginningOfLiteral(const Tokenizer::Token &) const;
bool BeginningOfPrimitiveLiteral(const Tokenizer::Token &) const;
bool BeginOfPropertyList(const Tokenizer::Token &) const;
+ bool BeginningOfScriptLiteral(const Tokenizer::Token &) const;
private:
std::string file;
class ParsedSource;
class Parser;
class PropertyList;
+class ScriptToken;
class Tokenizer;
class TypeDescription;
class Value;