From 238da3a706448d4c592460684e2a5a2c0eb81a04 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Oct 2012 13:56:25 +0200 Subject: [PATCH 01/16] implemented modulo operation for scripts --- src/common/Script.h | 3 +++ src/common/ScriptRunner.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/common/Script.h b/src/common/Script.h index 93bc531..0dbaf4d 100644 --- a/src/common/Script.h +++ b/src/common/Script.h @@ -29,6 +29,9 @@ public: CODE_ADD_V0, CODE_ADD_V1, + CODE_MOD_I0, + CODE_MOD_I1, + CODE_RAND_I0, CODE_RAND_I1, diff --git a/src/common/ScriptRunner.cpp b/src/common/ScriptRunner.cpp index 110b702..c1022c4 100644 --- a/src/common/ScriptRunner.cpp +++ b/src/common/ScriptRunner.cpp @@ -93,6 +93,12 @@ void ScriptRunner::Exec(unsigned char code) { case Script::CODE_ADD_V1: vector1 += PopVector(); break; + case Script::CODE_MOD_I0: + integer0 %= PopInt(); + break; + case Script::CODE_MOD_I1: + integer1 %= PopInt(); + break; case Script::CODE_RAND_I0: integer0 = std::rand(); break; -- 2.39.2 From 963ed8ddb873e0638b55b38c5590db75db8254c8 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Oct 2012 14:44:38 +0200 Subject: [PATCH 02/16] added new tokens --- src/loader/Tokenizer.cpp | 24 ++++++++++++++++++++++-- src/loader/Tokenizer.h | 14 +++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/loader/Tokenizer.cpp b/src/loader/Tokenizer.cpp index 6acda5f..91ad8b9 100644 --- a/src/loader/Tokenizer.cpp +++ b/src/loader/Tokenizer.cpp @@ -77,15 +77,35 @@ Tokenizer::Token Tokenizer::ReadToken() { switch (c) { case Token::ANGLE_BRACKET_OPEN: case Token::ANGLE_BRACKET_CLOSE: - case Token::CHEVRON_OPEN: - case Token::CHEVRON_CLOSE: case Token::COLON: case Token::COMMA: case Token::BRACKET_OPEN: case Token::BRACKET_CLOSE: case Token::PARENTHESIS_OPEN: case Token::PARENTHESIS_CLOSE: + case Token::COMMAND: + case Token::REGISTER: return Token ((Token::Type) c); + case '<': { + std::istream::char_type c2; + in.get(c2); + if (c2 == '<') { + return Token(Token::SCRIPT_BEGIN); + } else { + in.putback(c2); + return Token(Token::CHEVRON_OPEN); + } + } + case '>': { + std::istream::char_type c2; + in.get(c2); + if (c2 == '>') { + return Token(Token::SCRIPT_END); + } else { + in.putback(c2); + return Token(Token::CHEVRON_CLOSE); + } + } case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': diff --git a/src/loader/Tokenizer.h b/src/loader/Tokenizer.h index dff96fc..864f9d2 100644 --- a/src/loader/Tokenizer.h +++ b/src/loader/Tokenizer.h @@ -48,7 +48,11 @@ public: KEYWORD_TRUE = 't', IDENTIFIER = 'x', TYPE_NAME = 'n', - COMMENT = 'c' + COMMENT = 'c', + COMMAND = '$', + REGISTER = '%', + SCRIPT_BEGIN = 's', + SCRIPT_END = 'S', }; Token() : type(UNKNOWN), number(0) { } @@ -111,6 +115,8 @@ inline const char *TokenTypeToString(Tokenizer::Token::Type t) { return "COLON"; case Tokenizer::Token::COMMA: return "COMMA"; + case Tokenizer::Token::COMMAND: + return "COMMAND"; case Tokenizer::Token::BRACKET_OPEN: return "BRACKET_OPEN"; case Tokenizer::Token::BRACKET_CLOSE: @@ -121,6 +127,12 @@ inline const char *TokenTypeToString(Tokenizer::Token::Type t) { return "PARENTHESIS_CLOSE"; case Tokenizer::Token::NUMBER: return "NUMBER"; + case Tokenizer::Token::REGISTER: + return "REGISTER"; + case Tokenizer::Token::SCRIPT_BEGIN: + return "SCRIPT_BEGIN"; + case Tokenizer::Token::SCRIPT_END: + return "SCRIPT_END"; case Tokenizer::Token::STRING: return "STRING"; case Tokenizer::Token::KEYWORD_EXPORT: -- 2.39.2 From 3a30342daecdb9ee050ab20fcb50819a599d6343 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Oct 2012 15:31:29 +0200 Subject: [PATCH 03/16] parse scripts --- src/loader/Interpreter.cpp | 5 ++- src/loader/ParsedSource.cpp | 81 +++++++++++++++++++++++++++++++++++++ src/loader/ParsedSource.h | 38 ++++++++++++++++- src/loader/Parser.cpp | 55 ++++++++++++++++++++++++- src/loader/Parser.h | 2 + src/loader/fwd.h | 1 + 6 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index e8d4ec9..8b9b56a 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -142,6 +142,8 @@ void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &l 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'; @@ -151,7 +153,6 @@ void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &l break; case Literal::OBJECT: throw Error("illogical branch: read literal object as non-object literal"); - break; } } @@ -213,6 +214,8 @@ void *Interpreter::GetObject(int typeId, const Value &v) { values[typeId].push_back(str); } break; + case Literal::SCRIPT: + throw Error("script compiler not implemented"); case Literal::STRING: { typeId = TypeDescription::GetTypeId("String"); diff --git a/src/loader/ParsedSource.cpp b/src/loader/ParsedSource.cpp index e1a1d0a..6b2fc80 100644 --- a/src/loader/ParsedSource.cpp +++ b/src/loader/ParsedSource.cpp @@ -279,6 +279,16 @@ Literal::Literal(const string &typeName, PropertyList *properties) } +Literal::Literal(const vector &s) +: props(0) +, script(s) +, i1(0), i2(0) +, i3(0), i4(0) +, b(false) +, type(SCRIPT) { + +} + Literal::~Literal() { switch (type) { case ARRAY_VALUES: @@ -294,6 +304,11 @@ Literal::~Literal() { case OBJECT: delete props; break; + case SCRIPT: + for (vector::const_iterator i(script.begin()), end(script.end()); i != end; ++i) { + delete *i; + } + break; default: break; } @@ -400,6 +415,14 @@ const PropertyList *Literal::GetProperties() const { } } +const vector &Literal::GetScript() const { + if (type == SCRIPT) { + return script; + } else { + throw runtime_error("tried to access script of non-script literal"); + } +} + Value::~Value() { if (isLiteral) { @@ -423,6 +446,61 @@ const std::string &Value::GetIdentifier() const { } } + +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"); + } +} + } @@ -477,6 +555,9 @@ ostream &operator <<(ostream &out, const loader::Literal &l) { case loader::Literal::OBJECT: out << "object of type " << l.GetTypeName(); break; + case loader::Literal::SCRIPT: + out << "script"; + break; } return out; } diff --git a/src/loader/ParsedSource.h b/src/loader/ParsedSource.h index 64baaaa..9ba5297 100644 --- a/src/loader/ParsedSource.h +++ b/src/loader/ParsedSource.h @@ -18,6 +18,38 @@ 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: @@ -30,7 +62,8 @@ public: PATH, STRING, VECTOR, - OBJECT + OBJECT, + SCRIPT, }; public: @@ -43,6 +76,7 @@ public: Literal(const std::string &); Literal(int x, int y); Literal(const std::string &typeName, PropertyList *properties); + explicit Literal(const std::vector &); ~Literal(); private: Literal(const Literal &); @@ -67,12 +101,14 @@ public: int GetY() const; const std::string &GetTypeName() const; const PropertyList *GetProperties() const; + const std::vector &GetScript() const; private: PropertyList *props; std::string typeName, str; std::vector values; std::vector propertyLists; + std::vector script; int i1, i2, i3, i4; bool b; Type type; diff --git a/src/loader/Parser.cpp b/src/loader/Parser.cpp index 183accb..52585c4 100644 --- a/src/loader/Parser.cpp +++ b/src/loader/Parser.cpp @@ -112,6 +112,7 @@ bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const { 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: @@ -142,6 +143,10 @@ bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const { 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()); @@ -218,7 +223,10 @@ Literal *Parser::ParseLiteral() { 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); @@ -340,6 +348,51 @@ Literal *Parser::ParseVector() { 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 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::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)); diff --git a/src/loader/Parser.h b/src/loader/Parser.h index 392e9b7..963c377 100644 --- a/src/loader/Parser.h +++ b/src/loader/Parser.h @@ -62,6 +62,7 @@ private: Literal *ParseArray(); Literal *ParseColor(); Literal *ParseVector(); + Literal *ParseScript(); private: void AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected); @@ -69,6 +70,7 @@ private: 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; diff --git a/src/loader/fwd.h b/src/loader/fwd.h index 2f90849..b8b8458 100644 --- a/src/loader/fwd.h +++ b/src/loader/fwd.h @@ -20,6 +20,7 @@ class PagedAllocator; class ParsedSource; class Parser; class PropertyList; +class ScriptToken; class Tokenizer; class TypeDescription; class Value; -- 2.39.2 From fa339aa45524243e716fd234a09c929d0eec95f8 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Oct 2012 15:34:33 +0200 Subject: [PATCH 04/16] less verbose token code in parser --- src/loader/Parser.cpp | 206 +++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 102 deletions(-) diff --git a/src/loader/Parser.cpp b/src/loader/Parser.cpp index 52585c4..8ba3704 100644 --- a/src/loader/Parser.cpp +++ b/src/loader/Parser.cpp @@ -17,6 +17,8 @@ using std::ifstream; using std::string; using std::vector; +typedef loader::Tokenizer::Token Token; + namespace loader { Parser::Parser(const string &file, ParsedSource &product) @@ -37,15 +39,15 @@ void Parser::Parse() { } void Parser::ParseStatement() { - Tokenizer::Token t(GetToken()); + Token t(GetToken()); switch (t.type) { - case Tokenizer::Token::KEYWORD_EXPORT: + case Token::KEYWORD_EXPORT: ParseExportDirective(); break; - case Tokenizer::Token::KEYWORD_INCLUDE: + case Token::KEYWORD_INCLUDE: ParseIncludeDirective(); break; - case Tokenizer::Token::TYPE_NAME: + case Token::TYPE_NAME: tok.Putback(t); { Declaration *decl(ProbeDefinition()); @@ -57,15 +59,15 @@ void Parser::ParseStatement() { } } -Tokenizer::Token Parser::GetToken() try { +Token Parser::GetToken() try { return tok.GetNext(); } catch (Tokenizer::LexerError &e) { throw Error(file, e.Line(), e.what()); } void Parser::ParseExportDirective() { - Tokenizer::Token t(GetToken()); - if (t.type != Tokenizer::Token::IDENTIFIER) { + Token t(GetToken()); + if (t.type != Token::IDENTIFIER) { tok.Putback(t); Declaration *decl(ProbeDefinition()); product.ExportDeclaration(decl); @@ -75,8 +77,8 @@ void Parser::ParseExportDirective() { } void Parser::ParseIncludeDirective() { - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::STRING); + Token t(GetToken()); + AssertTokenType(t.type, Token::STRING); Parser sub(CatPath(dirname, t.str), product); sub.Parse(); } @@ -86,7 +88,7 @@ Declaration *Parser::ProbeDefinition() { string identifier(ParseIdentifier()); if (tok.HasMore()) { - Tokenizer::Token t(GetToken()); + Token t(GetToken()); tok.Putback(t); if (BeginOfPropertyList(t)) { auto_ptr propertyList(ParsePropertyList()); @@ -105,53 +107,53 @@ Declaration *Parser::ProbeDefinition() { return new Declaration(typeName, identifier); } -bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const { +bool Parser::BeginningOfLiteral(const Token &t) const { switch (t.type) { - case Tokenizer::Token::CHEVRON_OPEN: - case Tokenizer::Token::COLON: - 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: - case Tokenizer::Token::TYPE_NAME: + case Token::CHEVRON_OPEN: + case Token::COLON: + case Token::BRACKET_OPEN: + case Token::PARENTHESIS_OPEN: + case Token::NUMBER: + case Token::SCRIPT_BEGIN: + case Token::STRING: + case Token::KEYWORD_FALSE: + case Token::KEYWORD_TRUE: + case Token::TYPE_NAME: return true; default: return false; } } -bool Parser::BeginningOfPrimitiveLiteral(const Tokenizer::Token &t) const { +bool Parser::BeginningOfPrimitiveLiteral(const Token &t) const { switch (t.type) { - case Tokenizer::Token::CHEVRON_OPEN: - case Tokenizer::Token::COLON: - case Tokenizer::Token::BRACKET_OPEN: - case Tokenizer::Token::PARENTHESIS_OPEN: - case Tokenizer::Token::NUMBER: - case Tokenizer::Token::STRING: - case Tokenizer::Token::KEYWORD_FALSE: - case Tokenizer::Token::KEYWORD_TRUE: + case Token::CHEVRON_OPEN: + case Token::COLON: + case Token::BRACKET_OPEN: + case Token::PARENTHESIS_OPEN: + case Token::NUMBER: + case Token::STRING: + case Token::KEYWORD_FALSE: + case Token::KEYWORD_TRUE: return true; default: return false; } } -bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const { - return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN; +bool Parser::BeginOfPropertyList(const Token &t) const { + return t.type == Token::ANGLE_BRACKET_OPEN; } -bool Parser::BeginningOfScriptLiteral(const Tokenizer::Token &t) const { - return t.type == Tokenizer::Token::SCRIPT_BEGIN; +bool Parser::BeginningOfScriptLiteral(const Token &t) const { + return t.type == Token::SCRIPT_BEGIN; } Definition *Parser::ParseDefinition() { string typeName(ParseTypeName()); string identifier(ParseIdentifier()); - Tokenizer::Token t(GetToken()); + Token t(GetToken()); tok.Putback(t); if (BeginOfPropertyList(t)) { PropertyList *propertyList(ParsePropertyList()); @@ -169,35 +171,35 @@ Definition *Parser::ParseDefinition() { } string Parser::ParseIdentifier() { - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER); + Token t(GetToken()); + AssertTokenType(t.type, Token::IDENTIFIER); return t.str; } string Parser::ParseTypeName() { - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME); + Token t(GetToken()); + AssertTokenType(t.type, Token::TYPE_NAME); return t.str; } PropertyList *Parser::ParsePropertyList() { - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN); + Token t(GetToken()); + AssertTokenType(t.type, Token::ANGLE_BRACKET_OPEN); auto_ptr props(new PropertyList); - while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) { - Tokenizer::Token name(GetToken()); - AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER); + while (t.type != Token::ANGLE_BRACKET_CLOSE) { + Token name(GetToken()); + AssertTokenType(name.type, Token::IDENTIFIER); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::COLON); + AssertTokenType(t.type, Token::COLON); Value *value(ParseValue()); props->SetProperty(name.str, value); t = GetToken(); - if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) { + if (t.type != Token::ANGLE_BRACKET_CLOSE && t.type != Token::COMMA) { throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }"); } } @@ -206,8 +208,8 @@ PropertyList *Parser::ParsePropertyList() { } Value *Parser::ParseValue() { - Tokenizer::Token t(GetToken()); - if (t.type == Tokenizer::Token::IDENTIFIER) { + Token t(GetToken()); + if (t.type == Token::IDENTIFIER) { return new Value(t.str); } else if (BeginningOfLiteral(t)) { tok.Putback(t); @@ -219,8 +221,8 @@ Value *Parser::ParseValue() { } Literal *Parser::ParseLiteral() { - Tokenizer::Token t(GetToken()); - if (t.type == Tokenizer::Token::TYPE_NAME) { + Token t(GetToken()); + if (t.type == Token::TYPE_NAME) { PropertyList *props(ParsePropertyList()); return new Literal(t.str, props); } else if (BeginningOfScriptLiteral(t)) { @@ -228,26 +230,26 @@ Literal *Parser::ParseLiteral() { return ParseScript(); } else if (BeginningOfPrimitiveLiteral(t)) { switch (t.type) { - case Tokenizer::Token::CHEVRON_OPEN: + case Token::CHEVRON_OPEN: tok.Putback(t); return ParseVector(); - case Tokenizer::Token::COLON: + case Token::COLON: t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::STRING); + AssertTokenType(t.type, Token::STRING); return new Literal(dirname, t.str); - case Tokenizer::Token::BRACKET_OPEN: + case Token::BRACKET_OPEN: tok.Putback(t); return ParseArray(); - case Tokenizer::Token::PARENTHESIS_OPEN: + case Token::PARENTHESIS_OPEN: tok.Putback(t); return ParseColor(); - case Tokenizer::Token::NUMBER: + case Token::NUMBER: return new Literal(t.number); - case Tokenizer::Token::STRING: + case Token::STRING: return new Literal(t.str); - case Tokenizer::Token::KEYWORD_FALSE: + case Token::KEYWORD_FALSE: return new Literal(false); - case Tokenizer::Token::KEYWORD_TRUE: + case Token::KEYWORD_TRUE: return new Literal(true); default: throw std::logic_error("literal switch reached impossible default branch oO"); @@ -258,19 +260,19 @@ Literal *Parser::ParseLiteral() { } Literal *Parser::ParseArray() { - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN); + Token t(GetToken()); + AssertTokenType(t.type, Token::BRACKET_OPEN); - Tokenizer::Token probe(GetToken()); + Token probe(GetToken()); - if (probe.type == Tokenizer::Token::TYPE_NAME) { + if (probe.type == Token::TYPE_NAME) { vector values; - while (t.type != Tokenizer::Token::BRACKET_CLOSE) { + while (t.type != Token::BRACKET_CLOSE) { PropertyList *value(ParsePropertyList()); values.push_back(value); t = GetToken(); - if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) { + if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) { throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]"); } } @@ -279,12 +281,12 @@ Literal *Parser::ParseArray() { tok.Putback(probe); vector values; - while (t.type != Tokenizer::Token::BRACKET_CLOSE) { + while (t.type != Token::BRACKET_CLOSE) { Value *value(ParseValue()); values.push_back(value); t = GetToken(); - if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) { + if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) { throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]"); } } @@ -294,33 +296,33 @@ Literal *Parser::ParseArray() { Literal *Parser::ParseColor() { string msg("error parsing color"); - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg); + Token t(GetToken()); + AssertTokenType(t.type, Token::PARENTHESIS_OPEN, msg); - Tokenizer::Token red(GetToken()); - AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color"); + Token red(GetToken()); + AssertTokenType(red.type, Token::NUMBER, "error parsing red component of color"); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::COMMA, msg); + AssertTokenType(t.type, Token::COMMA, msg); - Tokenizer::Token green(GetToken()); - AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color"); + Token green(GetToken()); + AssertTokenType(green.type, Token::NUMBER, "error parsing green component of color"); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::COMMA, msg); + AssertTokenType(t.type, Token::COMMA, msg); - Tokenizer::Token blue(GetToken()); - AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color"); + Token blue(GetToken()); + AssertTokenType(blue.type, Token::NUMBER, "error parsing blue component of color"); t = GetToken(); - if (t.type == Tokenizer::Token::PARENTHESIS_CLOSE) { + if (t.type == Token::PARENTHESIS_CLOSE) { return new Literal(red.number, green.number, blue.number); - } else if (t.type != Tokenizer::Token::COMMA) { - Tokenizer::Token alpha(GetToken()); - AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color"); + } else if (t.type != Token::COMMA) { + Token alpha(GetToken()); + AssertTokenType(alpha.type, Token::NUMBER, "error parsing alpha component of color"); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg); + AssertTokenType(t.type, Token::PARENTHESIS_CLOSE, msg); return new Literal(red.number, green.number, blue.number, alpha.number); } else { @@ -330,50 +332,50 @@ Literal *Parser::ParseColor() { Literal *Parser::ParseVector() { std::string msg("error parsing vector"); - Tokenizer::Token t(GetToken()); - AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg); + Token t(GetToken()); + AssertTokenType(t.type, Token::CHEVRON_OPEN, msg); - Tokenizer::Token x(GetToken()); - AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector"); + Token x(GetToken()); + AssertTokenType(x.type, Token::NUMBER, "error parsing x component of vector"); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::COMMA, msg); + AssertTokenType(t.type, Token::COMMA, msg); - Tokenizer::Token y(GetToken()); - AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector"); + Token y(GetToken()); + AssertTokenType(y.type, Token::NUMBER, "error parsing y component of vector"); t = GetToken(); - AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg); + AssertTokenType(t.type, Token::CHEVRON_CLOSE, msg); 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); + Token t(GetToken()); + AssertTokenType(t.type, Token::SCRIPT_BEGIN, msg); vector script; try { - while (t.type != Tokenizer::Token::SCRIPT_END) { + while (t.type != 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); + case Token::COMMAND: { + Token t2(GetToken()); + AssertTokenType(t.type, Token::IDENTIFIER, msg); script.push_back(new ScriptToken(t2.str, ScriptToken::COMMAND)); break; } - case Tokenizer::Token::IDENTIFIER: { + case 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); + case Token::REGISTER: { + Token t2(GetToken()); + AssertTokenType(t.type, Token::IDENTIFIER, msg); script.push_back(new ScriptToken(t2.str, ScriptToken::REGISTER)); break; } @@ -393,13 +395,13 @@ Literal *Parser::ParseScript() { } -void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) { +void Parser::AssertTokenType(Token::Type actual, Token::Type expected) { if (expected != actual) { throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected)); } } -void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) { +void Parser::AssertTokenType(Token::Type actual, Token::Type expected, const string &msg) { if (expected != actual) { throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected)); } -- 2.39.2 From 77915e0186f4fc0788054eb34651c726b80d981c Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 14 Oct 2012 17:06:33 +0200 Subject: [PATCH 05/16] added script assembler --- src/loader/Interpreter.cpp | 260 ++++++++++++++++++++++++++++++++++++- src/loader/Interpreter.h | 5 + 2 files changed, 263 insertions(+), 2 deletions(-) diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index 8b9b56a..c2ce0d4 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -14,6 +14,7 @@ #include "../battle/Resources.h" #include "../common/Ikari.h" #include "../common/Item.h" +#include "../common/Script.h" #include "../common/Spell.h" #include "../common/Stats.h" #include "../common/TargetingMode.h" @@ -34,6 +35,7 @@ using battle::Monster; using battle::PartyLayout; using common::Ikari; using common::Item; +using common::Script; using common::Spell; using common::Stats; using common::TargetingMode; @@ -143,7 +145,9 @@ void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &l object[literal.GetString().size()] = '\0'; break; case Literal::SCRIPT: - throw Error("script compiler not implemented"); + new (object) Script; + ReadScript(literal.GetScript(), reinterpret_cast