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;