diff --git a/Rez/Expression.h b/Rez/Expression.h index 072b634a82..ec10db222e 100644 --- a/Rez/Expression.h +++ b/Rez/Expression.h @@ -61,7 +61,9 @@ class CompoundExpr : public Expression std::vector items; public: void addItem(ExprPtr item); - ExprPtr getItem(int i) { return items[i]; } + ExprPtr getItem(int i) const { return items[i]; } + int size() const { return items.size(); } + ~CompoundExpr(); }; diff --git a/Rez/ResourceDefinitions.cc b/Rez/ResourceDefinitions.cc index 695419627a..3af85e9524 100644 --- a/Rez/ResourceDefinitions.cc +++ b/Rez/ResourceDefinitions.cc @@ -101,3 +101,41 @@ void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass compiler->write(bitSize, actualValue); } + + +ArrayField::ArrayField(std::string name, ExprPtr count) + : name(name), arrayCount(count) +{ +} + +void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) +{ + CompoundExprPtr compound = std::dynamic_pointer_cast(expr); + assert(compound); + + + int i = 0; + int n = compound->size(); + + int iterations = 0; + while(i < n) + { + ++iterations; + for(FieldPtr f : fields) + { + if(f->needsValue()) + { + assert(i < n); + f->compile(compound->getItem(i++), compiler, prePass); + } + else + f->compile(nullptr, compiler, prePass); + } + } + + if(arrayCount) + { + int expected = arrayCount->evaluateInt(compiler); + assert(expected == iterations); + } +} diff --git a/Rez/ResourceDefinitions.h b/Rez/ResourceDefinitions.h index a19985b341..085c1cf629 100644 --- a/Rez/ResourceDefinitions.h +++ b/Rez/ResourceDefinitions.h @@ -108,6 +108,18 @@ public: }; typedef std::shared_ptr FieldListPtr; + +class ArrayField : public FieldList +{ + std::string name; + ExprPtr arrayCount; +public: + ArrayField(std::string name /* or empty */, ExprPtr count /* may be null*/); + + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); +}; +typedef std::shared_ptr ArrayFieldPtr; + class TypeDefinition : public FieldList { }; diff --git a/Rez/RezParser.yy b/Rez/RezParser.yy index c2ec800ff1..8875ad5da5 100644 --- a/Rez/RezParser.yy +++ b/Rez/RezParser.yy @@ -156,7 +156,7 @@ field_definitions : %empty %type field_definition; field_definition: simple_field_definition { $$ = $1; } - | array_definition { $$ = nullptr; } + | array_definition { $$ = $1; } | switch_definition { $$ = nullptr; } | fill_statement { $$ = nullptr; } | align_statement { $$ = nullptr; } @@ -207,13 +207,25 @@ align_statement : "align" fill_unit; fill_unit : "bit" | "byte" | "word" | "long"; - -array_definition: array_attributes "array" array_name_opt array_count_opt "{" field_definitions "}" ; +%type array_definition; +array_definition: + array_attributes "array" array_name_opt array_count_opt + { + ArrayFieldPtr af = std::make_shared($array_name_opt, $array_count_opt); + world.fieldLists.push(af); + } + "{" field_definitions "}" + { + $$ = world.fieldLists.top(); + world.fieldLists.pop(); + } + ; array_count : "[" expression "]" { $$ = $2; } -array_count_opt : %empty { $$ = nullptr; } | array_count; +array_count_opt : %empty { $$ = nullptr; } | array_count { $$ = $1; }; -array_name_opt : %empty | IDENTIFIER ; +%type array_name_opt; +array_name_opt : %empty { $$ = ""; } | IDENTIFIER { $$ = $1; } ; array_attributes: %empty | "wide" ;