diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 30a06d42f73bfc52d1d15985526fd944b1704938..39022b9eab98e8a8a3d7b64a96abf9edbed0dac1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,4 @@
 before_script:
-  - git clone https://git.dynare.org/Dynare/dynare.git
   - git clone https://git.dynare.org/Dynare/dseries.git
 
 testsuite_matlab:
diff --git a/Makefile b/Makefile
index 49caf2f1e179303154e390f31655ade6216f4856..450b157a8b38692ae3836f388947b953fe84d613 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ all: check-octave check-matlab
 
 check-octave:
 	@cd test ;\
-	$(OCTAVE) --silent --no-history runtest.m && [ -f report.pdf ]
+	$(OCTAVE) --no-init-file --silent --no-history --eval "addpath([pwd() '/../dseries/src']); addpath([pwd() '/../src']); runtest;" && [ -f report.pdf ]
 
 check-matlab:
-	@$(MATLAB) -nosplash -nodisplay -r "cd test; runtest; quit" && [ -f test/report.pdf ]
+	@$(MATLAB) -nosplash -nodisplay -r "addpath dseries/src; addpath src; cd test; runtest; quit" && [ -f test/report.pdf ]
diff --git a/initialize_reporting_toolbox.m b/initialize_reporting_toolbox.m
deleted file mode 100644
index fde692ab55ba611bba1e80fe41a60406afb0db39..0000000000000000000000000000000000000000
--- a/initialize_reporting_toolbox.m
+++ /dev/null
@@ -1,34 +0,0 @@
-% Script to set the necessary paths for the Reporting toolbox
-
-% Copyright (C) 2015-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-% Find reporting source directory
-reporting_src_root = [strrep(which('initialize_reporting_toolbox'),'initialize_reporting_toolbox.m','') 'src'];
-
-% Add path to reporting source
-addpath(reporting_src_root);
-addpath([reporting_src_root filesep '..' filesep 'macros']);
-
-% Reminder to add and initialize dates & dseries toolboxes
-if ~exist('emptydatesobject', 'var')
-    disp('Remember to add the paths to the dates toolbox before working with the reporting toolbox');
-end
-
-if ~exist('emptydseriesobject', 'var')
-    disp('Remember to add the paths to the dseries toolbox before working with the reporting toolbox');
-end
diff --git a/src/@graph/addSeries.m b/src/@graph/addSeries.m
index 971e0ebb009dadedf619f77a3d1f5496739f9df5..8a567e4e74de8ba0d025f85e8313dcc96e5e0a27 100644
--- a/src/@graph/addSeries.m
+++ b/src/@graph/addSeries.m
@@ -1,7 +1,18 @@
 function o = addSeries(o, varargin)
-% function o = addSeries(o, varargin)
+%function o = addSeries(o, varargin)
+% Add a series
+%
+% INPUTS
+%   o          [graph] graph object
+%   varargin           arguments to report_series()
+%
+% OUTPUTS
+%   updated section object
+%
+% SPECIAL REQUIREMENTS
+%   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
diff --git a/src/@graph/graph.m b/src/@graph/graph.m
index 788fa606170bf1ed004239f91595f722599153d8..8170e27b68123b51584c53f20629ab3814f3f73d 100644
--- a/src/@graph/graph.m
+++ b/src/@graph/graph.m
@@ -1,219 +1,220 @@
-function o = graph(varargin)
-%function o = graph(varargin)
-% Graph Class Constructor
-%
-% INPUTS
-%   varargin        0 args  : empty graph object
-%                   1 arg   : must be graph object (return a copy of arg)
-%                   > 1 args: option/value pairs (see structure below for
-%                   options)
-%
-% OUTPUTS
-%   o   [graph] graph object
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-o = struct;
-
-o.series = {};
-
-o.title = '';
-o.titleFormat = '';
-o.titleFontSize = 'normalsize';
-o.ylabel = '';
-o.xlabel = '';
-
-o.axisShape = 'box';
-
-o.graphDirName = 'tmpRepDir';
-o.graphName = '';
-o.data = '';
-o.seriesToUse = '';
-o.xrange = '';
-o.xAxisTight = true;
-o.yrange = '';
-o.yAxisTight = false;
-
-o.shade = '';
-o.shadeColor = 'green';
-o.shadeOpacity = 20;
-
-o.showGrid = true;
-
-o.showLegend = false;
-o.legendAt = [];
-o.showLegendBox = false;
-o.legendLocation = 'south east';
-o.legendOrientation = 'horizontal';
-o.legendFontSize = 'tiny';
-
-o.showZeroline = false;
-o.zeroLineColor = 'black';
-
-o.xTicks = [];
-o.xTickLabels = {};
-o.xTickLabelRotation = 0;
-o.xTickLabelAnchor = 'east';
-
-o.yTickLabelScaled = true;
-o.yTickLabelPrecision = 0;
-o.yTickLabelFixed = true;
-o.yTickLabelZeroFill = true;
-
-o.tickFontSize = 'normalsize';
-
-o.width = 6;
-o.height = 4.5;
-
-o.miscTikzPictureOptions = '';
-o.miscTikzAxisOptions = '';
-
-o.writeCSV = false;
-
-if nargin == 1
-    assert(isa(varargin{1}, 'graph'),['@graph.graph: with one arg you ' ...
-                        'must pass a graph object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@graph.graph: options must be supplied in name/value ' ...
-               'pairs.']);
+classdef graph < handle
+    % graph Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (Access = private)
+        series = {}
     end
-
-    optNames = fieldnames(o);
-
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@graph.graph: %s is not a recognized option.', pair{1});
-        end
+    properties (SetAccess = private)
+        title = ''                       % With one entry (a STRING), the title of the page. With more than one entry (a CELL_ARRAY_STRINGS), the title and subtitle(s) of the page. Values passed must be valid LATEX code (e.g., % must be \%). Default: none.
+        titleFormat = ''                 % The format to use for the graph title. Unlike other titleFormat options, due to a constraint of TikZ, this format applies to the title and subtitles. Default: TikZ default.
+        titleFontSize = 'normalsize'     % The font size for title. Default: normalsize.
+        ylabel = ''                      % The x-axis label. Default: none.
+        xlabel = ''                      % The y-axis label. Default: none.
+        axisShape = 'box'                % The shape the axis should have. `box' means that there is an axis line to the left, right, bottom, and top of the graphed line(s). ?L??? means that there is an axis to the left and bottom of the graphed line(s). Default: `box'.
+        graphDirName = 'tmpRepDir'       % The name of the folder in which to store this figure. Default: tmpRepDir.
+        graphName = ''                   % The name to use when saving this figure. Default: something of the form graph_pg1_sec2_row1_col3.tex.
+        data = ''                        % The dseries that provides the data for the graph. Default: none.
+        seriesToUse = ''                 % The names of the series contained in the dseries provided to the data option. If empty, use all series provided to data option. Default: empty.
+        xrange = ''                      % The boundary on the x-axis to display in the graph. Default: all.
+        xAxisTight = true                % Use a tight x axis. If false, uses PGFPLOTS/TikZ enlarge x limits to choose appropriate axis size. Default: true.
+        yrange = ''                      % The boundary on the y-axis to display in the graph, represented as a NUMERICAL_VECTOR of size 2, with the first entry less than the second entry. Default: all.
+        yAxisTight = false               % Use a tight y axis. If false, uses PGFPLOTS/TikZ enlarge y limits to choose appropriate axis size. Default: false.
+        shade = ''                       % The date range showing the portion of the graph that should be shaded. Default: none.
+        shadeColor = 'green'             % The color to use in the shaded portion of the graph. All valid color strings defined for use by PGFPLOTS/TikZ are valid. Furthermore, You can use combinations of these colors. For example, if you wanted a color that is 20% green and 80% purple, you could pass the string 'green!20!purple'. You can also use RGB colors, following the syntax: `rgb,255:red,231;green,84;blue,121' which corresponds to the RGB color (231;84;121). More examples are available in the section 4.7.5 of the PGFPLOTS/TikZ manual, revision 1.10. Default: `green'
+        shadeOpacity = 20                % The opacity of the shaded area, must be in [0,100]. Default: 20.
+        showGrid = true                  % Whether or not to display the major grid on the graph. Default: true.
+        showLegend = false               % Whether or not to display the legend. Unless you use the graphLegendName option, the name displayed in the legend is the tex name associated with the dseries. You can modify this tex name by using tex_rename. Default: false.
+        legendAt = []                    % The coordinates for the legend location. If this option is passed, it overrides the legendLocation option. Must be of size 2. Default: empty.
+        showLegendBox = false            % Whether or not to display a box around the legend. Default: false.
+        legendLocation = 'south east'    % Where to place the legend in the graph. Default: `south east'.
+        legendOrientation = 'horizontal' % Orientation of the legend. Default: `horizontal'.
+        legendFontSize = 'tiny'          % The font size for legend entries. Default: tiny.
+        showZeroline = false             % Display a solid black line at y = 0. Default: false.
+        zeroLineColor = 'black'          % The color to use for the zero line. Only used if showZeroLine is true. See the explanation in shadeColor for how to use colors with reports. Default: `black'.
+        xTicks = []                      % Used only in conjunction with xTickLabels, this option denotes the numerical position of the label along the x-axis. The positions begin at 1. Default: the indices associated with the first and last dates of the dseries and, if passed, the index associated with the first date of the shade option.
+        xTickLabels = {}                 % The labels to be mapped to the ticks provided by xTicks. Default: the first and last dates of the dseries and, if passed, the date first date of the shade option.
+        xTickLabelRotation = 0           % The amount to rotate the x tick labels by. Default: 0.
+        xTickLabelAnchor = 'east'        % Where to anchor the x tick label. Default: `east'.
+        yTickLabelScaled = true          % Determines whether or not there is a common scaling factor for the y axis. Default: true.
+        yTickLabelPrecision = 0          % The precision with which to report the yTickLabel. Default: 0.
+        yTickLabelFixed = true           % Round the y tick labels to a fixed number of decimal places, given by yTickLabelPrecision. Default: true.
+        yTickLabelZeroFill = true        % Whether or not to fill missing precision spots with zeros. Default: true.
+        tickFontSize = 'normalsize'      % The font size for x- and y-axis tick labels. Default: normalsize.
+        width = 6                        % The width of the graph, in inches. Default: 6.0.
+        height = 4.5                     % The height of the graph, in inches. Default: 4.5.
+        miscTikzPictureOptions = ''      % If you are comfortable with PGFPLOTS/TikZ, you can use this option to pass arguments directly to the PGFPLOTS/TikZ tikzpicture environment command. (e.g., to scale the graph in the x and y dimensions, you can pass following to this option: ?xscale=2.5, yscale=0.5?). Specifically to be used for desired ``PGFPLOTS/TikZoptionsthathavenotbeenincorporatedinto Dynare Reporting. Default: empty.
+        miscTikzAxisOptions = ''         % If you are comfortable with PGFPLOTS/TikZ, you can use this option to pass arguments directly to the PGFPLOTS/TikZ axis environment command. Specifically to be used for desired PGFPLOTS/ TikZ options that have not been incorporated into Dynare Reporting. Default: empty.
+        writeCSV = false                 % Whether or not to write a CSV file with only the plotted data. The file will be saved in the directory specified by graphDirName with the same base name as specified by graphName with the ending .csv. Default: false.
     end
-end
-
-% Check options provided by user
-if ischar(o.title)
-    o.title = {o.title};
-end
-assert(iscellstr(o.title), '@graph.graph: title must be a cell array of string(s)');
-assert(ischar(o.titleFormat), '@graph.graph: titleFormat file must be a string');
-assert(ischar(o.xlabel), '@graph.graph: xlabel file must be a string');
-assert(ischar(o.ylabel), '@graph.graph: ylabel file must be a string');
-assert(ischar(o.miscTikzPictureOptions), '@graph.graph: miscTikzPictureOptions file must be a string');
-assert(ischar(o.miscTikzAxisOptions), '@graph.graph: miscTikzAxisOptions file must be a string');
-assert(ischar(o.graphName), '@graph.graph: graphName must be a string');
-assert(ischar(o.graphDirName), '@graph.graph: graphDirName must be a string');
-assert(islogical(o.showGrid), '@graph.graph: showGrid must be either true or false');
-assert(islogical(o.xAxisTight), '@graph.graph: xAxisTight must be either true or false');
-assert(islogical(o.yAxisTight), '@graph.graph: yAxisTight must be either true or false');
-assert(islogical(o.showLegend), '@graph.graph: showLegend must be either true or false');
-assert(isempty(o.legendAt) || (isfloat(o.legendAt) && length(o.legendAt)==2), ...
-       '@graph.graph: legendAt must be a double array of size two');
-assert(islogical(o.showLegendBox), '@graph.graph: showLegendBox must be either true or false');
-assert(islogical(o.showZeroline), '@graph.graph: showZeroline must be either true or false');
-assert(isfloat(o.shadeOpacity) && length(o.shadeOpacity)==1 && ...
-       o.shadeOpacity >= 0 && o.shadeOpacity <= 100, ...
-       '@graph.graph: o.shadeOpacity must be a real in [0 100]');
-assert(isfloat(o.width), '@graph.graph: o.width must be a real number');
-assert(isfloat(o.height), '@graph.graph: o.height must be a real number');
-assert(isfloat(o.xTickLabelRotation), '@graph.graph: o.xTickLabelRotation must be a real number');
-assert(ischar(o.xTickLabelAnchor), '@graph.graph: xTickLabelAnchor must be a string');
-assert(isint(o.yTickLabelPrecision), '@graph.graph: o.yTickLabelPrecision must be an integer');
-assert(islogical(o.yTickLabelFixed), '@graph.graph: yTickLabelFixed must be either true or false');
-assert(islogical(o.yTickLabelZeroFill), '@graph.graph: yTickLabelZeroFill must be either true or false');
-assert(islogical(o.yTickLabelScaled), '@graph.graph: yTickLabelScaled must be either true or false');
-assert(islogical(o.writeCSV), '@graph.graph: writeCSV must be either true or false');
-assert(ischar(o.shadeColor), '@graph.graph: shadeColor must be a string');
-assert(ischar(o.zeroLineColor), '@graph.graph: zeroLineColor must be a string');
-assert(any(strcmp(o.axisShape, {'box', 'L'})), ['@graph.graph: axisShape ' ...
-                    'must be one of ''box'' or ''L''']);
-valid_legend_locations = ...
-    {'south west','south east','north west','north east','outer north east'};
-assert(any(strcmp(o.legendLocation, valid_legend_locations)), ...
-       ['@graph.graph: legendLocation must be one of ' addCommasToCellStr(valid_legend_locations)]);
-
-valid_font_sizes = {'tiny', 'scriptsize', 'footnotesize', 'small', ...
-                    'normalsize', 'large', 'Large', 'LARGE', 'huge', 'Huge'};
-assert(any(strcmp(o.legendFontSize, valid_font_sizes)), ...
-       ['@graph.graph: legendFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
-assert(any(strcmp(o.titleFontSize, valid_font_sizes)), ...
-       ['@graph.graph: titleFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
-assert(any(strcmp(o.tickFontSize, valid_font_sizes)), ...
-       ['@graph.graph: tickFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
-
-valid_legend_orientations = {'vertical', 'horizontal'};
-assert(any(strcmp(o.legendOrientation, valid_legend_orientations)), ...
-       ['@graph.graph: legendOrientation must be one of ' addCommasToCellStr(valid_legend_orientations)]);
-
-assert(isempty(o.shade) || (isdates(o.shade) && o.shade.ndat >= 2), ...
-       ['@graph.graph: shade is specified as a dates range, e.g. ' ...
-        '''dates(''1999q1''):dates(''1999q3'')''.']);
-assert(isempty(o.xrange) || (isdates(o.xrange) && o.xrange.ndat >= 2), ...
-       ['@graph.graph: xrange is specified as a dates range, e.g. ' ...
-        '''dates(''1999q1''):dates(''1999q3'')''.']);
-assert(isempty(o.yrange) || (isfloat(o.yrange) && length(o.yrange) == 2 && ...
-                             o.yrange(1) < o.yrange(2)), ...
-       ['@graph.graph: yrange is specified an array with two float entries, ' ...
-        'the lower bound and upper bound.']);
-assert(isempty(o.data) || isdseries(o.data), ['@graph.graph: data must ' ...
-                    'be a dseries']);
-assert(isempty(o.seriesToUse) || iscellstr(o.seriesToUse), ['@graph.graph: ' ...
-                    'seriesToUse must be a cell array of string(s)']);
-assert(isempty(o.xTicks) || isfloat(o.xTicks),...
-       '@graph.graph: xTicks must be a numerical array');
-assert(iscellstr(o.xTickLabels) || (ischar(o.xTickLabels) && strcmpi(o.xTickLabels, 'ALL')), ...
-       ['@graph.graph: xTickLabels must be a cell array of strings or ' ...
-        'equivalent to the string ''ALL''']);
-if ~isempty(o.xTickLabels)
-    assert((ischar(o.xTickLabels) && strcmpi(o.xTickLabels, 'ALL')) || ...
-           ~isempty(o.xTicks), ['@graph.graph: if you set xTickLabels and ' ...
-                        'it''s not equal to ''ALL'', you must set xTicks']);
-end
-if ~isempty(o.xTicks)
-    assert(~isempty(o.xTickLabels), '@graph.graph: if you set xTicks, you must set xTickLabels');
-end
-
-% using o.seriesToUse, create series objects and put them in o.series
-if ~isempty(o.data)
-    if isempty(o.seriesToUse)
-        for i=1:o.data.vobs
-            o.series{end+1} = report_series('data', o.data{o.data.name{i}});
-        end
-    else
-        for i=1:length(o.seriesToUse)
-            o.series{end+1} = report_series('data', o.data{o.seriesToUse{i}});
+    methods
+        function o = graph(varargin)
+            %function o = graph(varargin)
+            % Graph Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty graph object
+            %                   1 arg   : must be graph object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for
+            %                   options)
+            %
+            % OUTPUTS
+            %   o   [graph] graph object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'graph'), ...
+                    'With one arg to the Graph constructor, you must pass a graph object');
+                o = varargin{1};
+                return
+            elseif nargin > 1
+                if round(nargin/2) ~= nargin/2
+                    error('@graph.graph: options must be supplied in name/value pairs.');
+                end
+
+                % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+                warning('off')
+                optNames = fieldnames(o);
+                warning('on')
+
+                % overwrite default values
+                for pair = reshape(varargin, 2, [])
+                    ind = find(strcmpi(optNames, pair{1}));
+                    assert(isempty(ind) || length(ind) == 1);
+                    if ~isempty(ind)
+                        o.(optNames{ind}) = pair{2};
+                    else
+                        error('@graph.graph: %s is not a recognized option.', pair{1});
+                    end
+                end
+            end
+
+            % Check options provided by user
+            if ischar(o.title)
+                o.title = {o.title};
+            end
+            assert(iscellstr(o.title), '@graph.graph: title must be a cell array of string(s)');
+            assert(ischar(o.titleFormat), '@graph.graph: titleFormat file must be a string');
+            assert(ischar(o.xlabel), '@graph.graph: xlabel file must be a string');
+            assert(ischar(o.ylabel), '@graph.graph: ylabel file must be a string');
+            assert(ischar(o.miscTikzPictureOptions), '@graph.graph: miscTikzPictureOptions file must be a string');
+            assert(ischar(o.miscTikzAxisOptions), '@graph.graph: miscTikzAxisOptions file must be a string');
+            assert(ischar(o.graphName), '@graph.graph: graphName must be a string');
+            assert(ischar(o.graphDirName), '@graph.graph: graphDirName must be a string');
+            assert(islogical(o.showGrid), '@graph.graph: showGrid must be either true or false');
+            assert(islogical(o.xAxisTight), '@graph.graph: xAxisTight must be either true or false');
+            assert(islogical(o.yAxisTight), '@graph.graph: yAxisTight must be either true or false');
+            assert(islogical(o.showLegend), '@graph.graph: showLegend must be either true or false');
+            assert(isempty(o.legendAt) || (isfloat(o.legendAt) && length(o.legendAt)==2), ...
+                '@graph.graph: legendAt must be a double array of size two');
+            assert(islogical(o.showLegendBox), '@graph.graph: showLegendBox must be either true or false');
+            assert(islogical(o.showZeroline), '@graph.graph: showZeroline must be either true or false');
+            assert(isfloat(o.shadeOpacity) && length(o.shadeOpacity)==1 && ...
+                o.shadeOpacity >= 0 && o.shadeOpacity <= 100, ...
+                '@graph.graph: o.shadeOpacity must be a real in [0 100]');
+            assert(isfloat(o.width), '@graph.graph: o.width must be a real number');
+            assert(isfloat(o.height), '@graph.graph: o.height must be a real number');
+            assert(isfloat(o.xTickLabelRotation), '@graph.graph: o.xTickLabelRotation must be a real number');
+            assert(ischar(o.xTickLabelAnchor), '@graph.graph: xTickLabelAnchor must be a string');
+            assert(isint(o.yTickLabelPrecision), '@graph.graph: o.yTickLabelPrecision must be an integer');
+            assert(islogical(o.yTickLabelFixed), '@graph.graph: yTickLabelFixed must be either true or false');
+            assert(islogical(o.yTickLabelZeroFill), '@graph.graph: yTickLabelZeroFill must be either true or false');
+            assert(islogical(o.yTickLabelScaled), '@graph.graph: yTickLabelScaled must be either true or false');
+            assert(islogical(o.writeCSV), '@graph.graph: writeCSV must be either true or false');
+            assert(ischar(o.shadeColor), '@graph.graph: shadeColor must be a string');
+            assert(ischar(o.zeroLineColor), '@graph.graph: zeroLineColor must be a string');
+            assert(any(strcmp(o.axisShape, {'box', 'L'})), ['@graph.graph: axisShape ' ...
+                'must be one of ''box'' or ''L''']);
+            valid_legend_locations = ...
+                {'south west','south east','north west','north east','outer north east'};
+            assert(any(strcmp(o.legendLocation, valid_legend_locations)), ...
+                ['@graph.graph: legendLocation must be one of ' addCommasToCellStr(valid_legend_locations)]);
+
+            valid_font_sizes = {'tiny', 'scriptsize', 'footnotesize', 'small', ...
+                'normalsize', 'large', 'Large', 'LARGE', 'huge', 'Huge'};
+            assert(any(strcmp(o.legendFontSize, valid_font_sizes)), ...
+                ['@graph.graph: legendFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
+            assert(any(strcmp(o.titleFontSize, valid_font_sizes)), ...
+                ['@graph.graph: titleFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
+            assert(any(strcmp(o.tickFontSize, valid_font_sizes)), ...
+                ['@graph.graph: tickFontSize must be one of ' addCommasToCellStr(valid_font_sizes)]);
+
+            valid_legend_orientations = {'vertical', 'horizontal'};
+            assert(any(strcmp(o.legendOrientation, valid_legend_orientations)), ...
+                ['@graph.graph: legendOrientation must be one of ' addCommasToCellStr(valid_legend_orientations)]);
+
+            assert(isempty(o.shade) || (isdates(o.shade) && o.shade.ndat >= 2), ...
+                ['@graph.graph: shade is specified as a dates range, e.g. ' ...
+                '''dates(''1999q1''):dates(''1999q3'')''.']);
+            assert(isempty(o.xrange) || (isdates(o.xrange) && o.xrange.ndat >= 2), ...
+                ['@graph.graph: xrange is specified as a dates range, e.g. ' ...
+                '''dates(''1999q1''):dates(''1999q3'')''.']);
+            assert(isempty(o.yrange) || (isfloat(o.yrange) && length(o.yrange) == 2 && ...
+                o.yrange(1) < o.yrange(2)), ...
+                ['@graph.graph: yrange is specified an array with two float entries, ' ...
+                'the lower bound and upper bound.']);
+            assert(isempty(o.data) || isdseries(o.data), ['@graph.graph: data must ' ...
+                'be a dseries']);
+            assert(isempty(o.seriesToUse) || iscellstr(o.seriesToUse), ['@graph.graph: ' ...
+                'seriesToUse must be a cell array of string(s)']);
+            assert(isempty(o.xTicks) || isfloat(o.xTicks),...
+                '@graph.graph: xTicks must be a numerical array');
+            assert(iscellstr(o.xTickLabels) || (ischar(o.xTickLabels) && strcmpi(o.xTickLabels, 'ALL')), ...
+                ['@graph.graph: xTickLabels must be a cell array of strings or ' ...
+                'equivalent to the string ''ALL''']);
+            if ~isempty(o.xTickLabels)
+                assert((ischar(o.xTickLabels) && strcmpi(o.xTickLabels, 'ALL')) || ...
+                    ~isempty(o.xTicks), ['@graph.graph: if you set xTickLabels and ' ...
+                    'it''s not equal to ''ALL'', you must set xTicks']);
+            end
+            if ~isempty(o.xTicks)
+                assert(~isempty(o.xTickLabels), '@graph.graph: if you set xTicks, you must set xTickLabels');
+            end
+
+            % using o.seriesToUse, create series objects and put them in o.series
+            if ~isempty(o.data)
+                if isempty(o.seriesToUse)
+                    for i=1:o.data.vobs
+                        o.series{end+1} = report_series('data', o.data{o.data.name{i}});
+                    end
+                else
+                    for i=1:length(o.seriesToUse)
+                        o.series{end+1} = report_series('data', o.data{o.seriesToUse{i}});
+                    end
+                end
+            end
+            o.seriesToUse = '';
+            o.data = '';
+            if ~exist(o.graphDirName, 'file')
+                mkdir(o.graphDirName);
+            end
         end
     end
-end
-o = rmfield(o, 'seriesToUse');
-o = rmfield(o, 'data');
-
-if ~exist(o.graphDirName, 'file')
-    mkdir(o.graphDirName);
-end
-
-% Create graph object
-o = class(o, 'graph');
+    methods (Access = ?section, Hidden = true)
+        o = addSeries(o, varargin)
+        write(o, fid, pg, sec, row, col)
+    end
+    methods (Access = private)
+        % Methods defined in separate files
+        lastIndex = end(o, k, n)
+        graphName = writeGraphFile(o, pg, sec, row, col)
+    end
 end
diff --git a/src/@graph/subsasgn.m b/src/@graph/subsasgn.m
deleted file mode 100644
index 291423dfb5b819c195843c55989e023fef261018..0000000000000000000000000000000000000000
--- a/src/@graph/subsasgn.m
+++ /dev/null
@@ -1,49 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B.series{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@graph.subsasgn: field ' S.subs 'does not exist']);
-    end
-  case '{}'
-    assert(isint(S.subs{1}));
-    B{S.subs{1}} = V;
-  otherwise
-    error('@graph.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@graph/subsref.m b/src/@graph/subsref.m
deleted file mode 100644
index b6f68f8c603944587387c77ab851462893cbe783..0000000000000000000000000000000000000000
--- a/src/@graph/subsref.m
+++ /dev/null
@@ -1,53 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@graph.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    if isempty(S(1).subs{:})
-        A = A.series;
-    else
-        assert(isnumeric(S(1).subs{:}));
-        A = A.series{S(1).subs{:}};
-    end
-  case '{}'
-    A = A.series{S(1).subs{:}};
-  otherwise
-    error('@graph.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@graph/write.m b/src/@graph/write.m
index 64200d9ca9482a67461d35564b4f34eb461da682..e00cd9a162afc515026f6e16fe6f0d920cdf2c95 100644
--- a/src/@graph/write.m
+++ b/src/@graph/write.m
@@ -1,5 +1,5 @@
-function o = write(o, fid, pg, sec, row, col)
-%function o = write(o, fid, pg, sec, row, col)
+function write(o, fid, pg, sec, row, col)
+%function write(o, fid, pg, sec, row, col)
 % Write a Graph object
 %
 % INPUTS
@@ -16,7 +16,7 @@ function o = write(o, fid, pg, sec, row, col)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -34,6 +34,6 @@ function o = write(o, fid, pg, sec, row, col)
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 assert(fid ~= -1);
-o = writeGraphFile(o, pg, sec, row, col);
-fprintf(fid, '\\input{%s}', o.graphName);
+graphName = writeGraphFile(o, pg, sec, row, col);
+fprintf(fid, '\\input{%s}', graphName);
 end
\ No newline at end of file
diff --git a/src/@graph/writeGraphFile.m b/src/@graph/writeGraphFile.m
index 1c764203aea9c847a00e37445ae2e7f7d4ca6e73..d8d0d845772b85932ef8ee2800a92b47e39a4239 100644
--- a/src/@graph/writeGraphFile.m
+++ b/src/@graph/writeGraphFile.m
@@ -1,5 +1,5 @@
-function o = writeGraphFile(o, pg, sec, row, col)
-%function o = writeGraphFile(o, pg, sec, row, col)
+function graphName = writeGraphFile(o, pg, sec, row, col)
+%function graphName = writeGraphFile(o, pg, sec, row, col)
 % Write the tikz file that contains the graph
 %
 % INPUTS
@@ -10,7 +10,7 @@ function o = writeGraphFile(o, pg, sec, row, col)
 %   col [integer] this col number
 %
 % OUTPUTS
-%   o   [graph] graph object
+%   graphName   [string] name of graph written
 %
 % SPECIAL REQUIREMENTS
 %   none
@@ -35,16 +35,16 @@ function o = writeGraphFile(o, pg, sec, row, col)
 ne = length(o.series);
 if ne < 1
     warning('@graph.writeGraphFile: no series to plot, returning');
-    return;
+    return
 end
 
 if isempty(o.graphName)
-    o.graphName = sprintf('%s/graph_pg%d_sec%d_row%d_col%d.tex', o.graphDirName, pg, sec, row, col);
+    graphName = sprintf('%s/graph_pg%d_sec%d_row%d_col%d.tex', o.graphDirName, pg, sec, row, col);
 else
-    o.graphName = [o.graphDirName '/' o.graphName];
+    graphName = [o.graphDirName '/' o.graphName];
 end
 
-[fid, msg] = fopen(o.graphName, 'w');
+[fid, msg] = fopen(graphName, 'w');
 if fid == -1
     error(['@graph.writeGraphFile: ' msg]);
 end
@@ -301,17 +301,17 @@ for i=1:ne
     o.series{i}.writeSeriesForGraph(fid, dd, i);
     if o.writeCSV
         csvseries = [csvseries ...
-                     o.series{i}.data(dd).set_names([...
-                         o.series{i}.data.name{:} '_' ...
-                         o.series{i}.graphLegendName '_' ...
-                         o.series{i}.graphLineColor '_' ...
-                         o.series{i}.graphLineStyle '_' ...
-                         num2str(o.series{i}.graphLineWidth) '_' ...
-                         o.series{i}.graphMarker '_' ...
-                         o.series{i}.graphMarkerEdgeColor '_' ...
-                         o.series{i}.graphMarkerFaceColor '_' ...
-                         num2str(o.series{i}.graphMarkerSize)]) ...
-                    ];
+            o.series{i}.data(dd).set_names([...
+            o.series{i}.data.name{:} '_' ...
+            o.series{i}.graphLegendName '_' ...
+            o.series{i}.graphLineColor '_' ...
+            o.series{i}.graphLineStyle '_' ...
+            num2str(o.series{i}.graphLineWidth) '_' ...
+            o.series{i}.graphMarker '_' ...
+            o.series{i}.graphMarkerEdgeColor '_' ...
+            o.series{i}.graphMarkerFaceColor '_' ...
+            num2str(o.series{i}.graphMarkerSize)]) ...
+            ];
     end
     if o.showLegend
         le = o.series{i}.getNameForLegend();
diff --git a/src/@report/display.m b/src/@page/addData.m
similarity index 65%
rename from src/@report/display.m
rename to src/@page/addData.m
index a7dbef8987ecf2ee536325a1be1b88119fad8146..7d53690a349a92ea7530e2a32dd9ed4ee8839770 100644
--- a/src/@report/display.m
+++ b/src/@page/addData.m
@@ -1,17 +1,18 @@
-function display(o)
-%function display(o)
-% Display a Report object
+function o = addData(o, varargin)
+%function o = addData(o, varargin)
+% Add a series
 %
 % INPUTS
-%   o     [report]  report object
+%   o          [page]    page object
+%   varargin             arguments to report_data()
 %
 % OUTPUTS
-%   none
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,5 +29,7 @@ function display(o)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-display_reporting_object(o);
-end
\ No newline at end of file
+assert(~isempty(o.sections), ...
+       '@page.addData: Before adding data, you must add a section.');
+o.sections{end}.addData(varargin{:});
+end
diff --git a/src/@graph/display.m b/src/@page/addGraph.m
similarity index 64%
rename from src/@graph/display.m
rename to src/@page/addGraph.m
index ffc6c464b6396d342fc214ec9a1ca030fcde0473..b60c12053ff70a5d3cf14e6f42ef46ab4531f829 100644
--- a/src/@graph/display.m
+++ b/src/@page/addGraph.m
@@ -1,17 +1,18 @@
-function display(o)
-%function display(o)
-% Display a Graph object
+function o = addGraph(o, varargin)
+%function o = addGraph(o, varargin)
+% Add a report_table
 %
 % INPUTS
-%   o   [graph] graph object
+%   o          [page]    page object
+%   varargin             arguments to graph()
 %
 % OUTPUTS
-%   none
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,5 +29,7 @@ function display(o)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-display_reporting_object(o);
-end
\ No newline at end of file
+assert(~isempty(o.sections), ...
+       '@page.addGraph: Before adding a graph, you must add a section.');
+o.sections{end}.addGraph(varargin{:});
+end
diff --git a/src/allCellsAreDates.m b/src/@page/addParagraph.m
similarity index 64%
rename from src/allCellsAreDates.m
rename to src/@page/addParagraph.m
index b28e03baf61f34812c1b1596529672d6bdfdaf3c..56a55171938f8d3947f00c6892bb274f5fcf9afe 100644
--- a/src/allCellsAreDates.m
+++ b/src/@page/addParagraph.m
@@ -1,17 +1,18 @@
-function tf = allCellsAreDates(dcell)
-%function tf = allCellsAreDates(dcell)
-% Determines if all the elements of dcell are dates objects
+function o = addParagraph(o, varargin)
+%function o = addParagraph(o, varargin)
+% Add a series
 %
 % INPUTS
-%   dcell     cell of dates objects
+%   o          [page]    page object
+%   varargin             arguments to paragraph()
 %
 % OUTPUTS
-%   tf        true if every entry of dcell is a dates object
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2014-2015 Dynare Team
+% Copyright (C) 2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,12 +29,7 @@ function tf = allCellsAreDates(dcell)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(iscell(dcell));
-tf = true;
-for i=1:length(dcell)
-    if ~isdates(dcell{i})
-        tf = false;
-        return;
-    end
+assert(~isempty(o.sections), ...
+       '@page.addParagraph: Before adding a paragraph, you must add a section.');
+o.sections{end}.addParagraph(varargin{:});
 end
-end
\ No newline at end of file
diff --git a/src/@page/addSection.m b/src/@page/addSection.m
index d1649af6d5345cfca0b6b7cd99a41e15dd7f4f17..8644f1715bd2dd296c925043920d6ad13277beed 100644
--- a/src/@page/addSection.m
+++ b/src/@page/addSection.m
@@ -1,11 +1,10 @@
-function p = addSection(p, varargin)
-%function p = addSection(p, varargin)
-% Add a section to the Cell Array of sections in the report
+function o = addSection(o, varargin)
+%function o = addSection(o, varargin)
+% Add a section
 %
 % INPUTS
-%   1 args => add empty section
-%   2 args => add given section
-%   3 args => add section at index
+%   o          [page]    page object
+%   varargin             arguments to section()
 %
 % OUTPUTS
 %   updated page object
@@ -13,7 +12,7 @@ function p = addSection(p, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -30,5 +29,5 @@ function p = addSection(p, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-p.sections{end+1} = section(varargin{:});
+o.sections{end+1} = section(varargin{:});
 end
diff --git a/src/@page/display.m b/src/@page/addSeries.m
similarity index 64%
rename from src/@page/display.m
rename to src/@page/addSeries.m
index 6da16b296323c5c3a49517da1e109decdba294f3..e44ff8034e813f7d5d5b55e882d649c1d5b566fc 100644
--- a/src/@page/display.m
+++ b/src/@page/addSeries.m
@@ -1,17 +1,18 @@
-function display(o)
-%function display(o)
-% Display a Page object
+function o = addSeries(o, varargin)
+%function o = addSeries(o, varargin)
+% Add a series
 %
 % INPUTS
-%   o   [page] page object
+%   o          [page]    page object
+%   varargin             arguments to report_series()
 %
 % OUTPUTS
-%   none
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,5 +29,7 @@ function display(o)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-display_reporting_object(o);
-end
\ No newline at end of file
+assert(~isempty(o.sections), ...
+       '@page.addSeries: Before adding a series, you must add a section.');
+o.sections{end}.addSeries(varargin{:});
+end
diff --git a/src/@page/addTable.m b/src/@page/addTable.m
new file mode 100644
index 0000000000000000000000000000000000000000..63f56e95cd82ee184884ad9375b8f8980f631457
--- /dev/null
+++ b/src/@page/addTable.m
@@ -0,0 +1,35 @@
+function o = addTable(o, varargin)
+%function o = addTable(o, varargin)
+% Add a report_table
+%
+% INPUTS
+%   o          [page]    page object
+%   varargin             arguments to report_table()
+%
+% OUTPUTS
+%   updated section object
+%
+% SPECIAL REQUIREMENTS
+%   none
+
+% Copyright (C) 2019 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+
+assert(~isempty(o.sections), ...
+       '@page.addTable: Before adding a table, you must add a section.');
+o.sections{end}.addTable(varargin{:});
+end
diff --git a/src/@paragraph/display.m b/src/@page/addVspace.m
similarity index 64%
rename from src/@paragraph/display.m
rename to src/@page/addVspace.m
index 2587d3a80d27d7f497e577dfa59a71b5e43f0403..828f3a19558a3f98fb16aabcd49688a9181c13f1 100644
--- a/src/@paragraph/display.m
+++ b/src/@page/addVspace.m
@@ -1,17 +1,18 @@
-function display(o)
-%function display(o)
-% Display a Paragraph object
+function o = addVspace(o, varargin)
+%function o = addVspace(o, varargin)
+% Add a vspace
 %
 % INPUTS
-%   o   [paragraph] paragraph object
+%   o          [page]    page object
+%   varargin             arguments to vspace()
 %
 % OUTPUTS
-%   none
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2014-2015 Dynare Team
+% Copyright (C) 2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,5 +29,7 @@ function display(o)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-display_reporting_object(o);
-end
\ No newline at end of file
+assert(~isempty(o.sections), ...
+       '@page.addVspace: Before adding a vspace, you must add a section.');
+o.sections{end}.addVspace(varargin{:});
+end
diff --git a/src/@page/page.m b/src/@page/page.m
index 0afc3b63ce51e22a3b9a28e225956299326eaee2..44635f4ccdd137f0a642efa6d4a2940f88699b50 100644
--- a/src/@page/page.m
+++ b/src/@page/page.m
@@ -1,106 +1,124 @@
-function o = page(varargin)
-%function o = page(varargin)
-% Page Class Constructor
-%
-% INPUTS
-%   0 args => empty page
-%   1 arg (page class) => copy object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-o = struct;
-o.paper = '';
-o.title = {''};
-titleFormatDefalut = {'\large\bfseries'};
-o.titleFormat = titleFormatDefalut;
-o.titleTruncate = '';
-o.orientation = '';
-o.footnote = {};
-o.sections = {};
-
-o.pageDirName = 'tmpRepDir';
-o.latex = '';
-
-if nargin == 1
-    assert(isa(varargin{1}, 'page'), ['@page.page: with one arg to Page ' ...
-                        'constructor, you must pass a page object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@page.page: options must be supplied in name/value ' ...
-               'pairs.']);
+classdef page < handle
+    % page Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (Access = private, Constant = true)
+        titleFormatDefalut = {'\large\bfseries'}
     end
-
-    optNames = fieldnames(o);
-
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@page.page: %s is not a recognized option.', pair{1});
-        end
+    properties (Access = private)
+        sections = {}
     end
-end
+    properties (SetAccess = private)
+        paper = ''                % Paper size. Default: `a4'.
+        title = {''}              % With one entry (a STRING), the title of the page. With more than one entry (a CELL_ARRAY_STRINGS), the title and subtitle(s) of the page. Values passed must be valid LATEX code (e.g., % must be \%). Default: none.
+        titleFormat = ''          % A string representing the valid LATEX markup to use on title. The number of cell array entries must be equal to that of the title option if you do not want to use the default value for the title (and subtitles). Default: \large\bfseries.
+        titleTruncate = ''        % Useful when automatically generating page titles that may become too long, titleTruncate can be used to truncate a title (and subsequent subtitles) when they pass the specified number of characters. Default: .off.
+        orientation = ''          % Paper orientation: Default: `portrait'.
+        footnote = {}             % A footnote to be included at the bottom of this page. Default: none.
+        pageDirName = 'tmpRepDir' % The name of the folder in which to store this page. Only used when the latex command is passed. Default: tmpRepDir.
+        latex = ''                % The valid LATEX code to be used for this page. Alows the user to create a page to be included in the report by passing LATEX code directly. Default: empty.
+    end
+    methods (Access = ?report)
+        function o = page(varargin)
+            %function o = page(varargin)
+            % Page Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty page object
+            %                   1 arg   : must be page object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [page]  page object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            o.titleFormat = o.titleFormatDefalut;
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'page'), ...
+                    '@page.page: with one arg to Page constructor, you must pass a page object');
+                o = varargin{1};
+                return
+            end
 
-% Check options provided by user
-if ischar(o.title)
-    o.title = {o.title};
-end
-if ischar(o.titleFormat)
-    o.titleFormat = {o.titleFormat};
-end
-if length(o.title) ~= length(o.titleFormat)
-    o.titleFormat = repmat(titleFormatDefalut, 1, length(o.title));
-end
-assert(iscellstr(o.title), ...
-       '@page.page: title must be a cell array of strings');
-assert(iscellstr(o.titleFormat), ...
-       '@page.page: titleFormat must be a cell array of strings');
-assert((ischar(o.titleTruncate) && isempty(o.titleTruncate)) || ...
-       isint(o.titleTruncate), ...
-       '@page.page: titleTruncate must be empty or an integer.');
-assert(ischar(o.pageDirName), '@page.page: pageDirName must be a string');
-assert(ischar(o.latex), ...
-       '@page.page: latex must be a string');
-valid_paper = {'a4', 'letter'};
-assert(any(strcmp(o.paper, valid_paper)), ...
-       ['@page.page: paper must be one of ' addCommasToCellStr(valid_paper)]);
+            if round(nargin/2) ~= nargin/2
+                error('@page.page: options must be supplied in name/value pairs.');
+            end
 
-valid_orientation = {'portrait', 'landscape'};
-assert(any(strcmp(o.orientation, valid_orientation)), ...
-       ['@page.page: orientation must be one of ' addCommasToCellStr(valid_orientation)]);
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-if ischar(o.footnote)
-    o.footnote = {o.footnote};
-end
-assert(iscellstr(o.footnote), ...
-       '@page.page: footnote must be a cell array of string(s)');
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@page.page: %s is not a recognized option.', pair{1});
+                end
+            end
 
-% Create page object
-o = class(o, 'page');
+            % Check input
+            if ischar(o.title)
+                o.title = {o.title};
+            end
+            if ischar(o.titleFormat)
+                o.titleFormat = {o.titleFormat};
+            end
+            if length(o.title) ~= length(o.titleFormat)
+                o.titleFormat = repmat(o.titleFormatDefalut, 1, length(o.title));
+            end
+            assert(iscellstr(o.title), ...
+                '@page.page: title must be a cell array of strings');
+            assert(iscellstr(o.titleFormat), ...
+                '@page.page: titleFormat must be a cell array of strings');
+            assert((ischar(o.titleTruncate) && isempty(o.titleTruncate)) || ...
+                isint(o.titleTruncate), ...
+                '@page.page: titleTruncate must be empty or an integer.');
+            assert(ischar(o.pageDirName), '@page.page: pageDirName must be a string');
+            assert(ischar(o.latex), ...
+                '@page.page: latex must be a string');
+            valid_paper = {'a4', 'letter'};
+            assert(any(strcmp(o.paper, valid_paper)), ...
+                ['@page.page: paper must be one of ' addCommasToCellStr(valid_paper)]);
+            valid_orientation = {'portrait', 'landscape'};
+            assert(any(strcmp(o.orientation, valid_orientation)), ...
+                ['@page.page: orientation must be one of ' addCommasToCellStr(valid_orientation)]);
+            if ischar(o.footnote)
+                o.footnote = {o.footnote};
+            end
+            assert(iscellstr(o.footnote), ...
+                '@page.page: footnote must be a cell array of string(s)');
+            assert(isempty(o.sections), ...
+                '@page.page: sections is not a valid option');
+        end
+    end
+    methods (Access = ?report, Hidden = true)
+        o = addSection(o, varargin)
+        o = addVspace(o, varargin)
+        o = addTable(o, varargin)
+        write(o, fid, pg)
+        lastIndex = end(o, k, n)
+        ns = numSections(p)
+    end
 end
diff --git a/src/@page/subsasgn.m b/src/@page/subsasgn.m
deleted file mode 100644
index 71931c72ff526c5cafb2da776bf55b54bb47497f..0000000000000000000000000000000000000000
--- a/src/@page/subsasgn.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@page.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@page.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@page/subsref.m b/src/@page/subsref.m
deleted file mode 100644
index 6099f994766aa0f203373e86bf7c6a6782517ed2..0000000000000000000000000000000000000000
--- a/src/@page/subsref.m
+++ /dev/null
@@ -1,48 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@page.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    A = getSections(A, S(1).subs{:});
-  case '{}'
-    error(['@page.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@page.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@page/write.m b/src/@page/write.m
index b4871e69cc078fa22c471b52f353a9c061e24b4e..ce7ad21e31d40375b5c4346c0a0d10e1311e3fb8 100644
--- a/src/@page/write.m
+++ b/src/@page/write.m
@@ -1,5 +1,5 @@
-function o = write(o, fid, pg)
-%function o = write(o, fid, pg)
+function write(o, fid, pg)
+%function write(o, fid, pg)
 % Write a Page object
 %
 % INPUTS
@@ -40,7 +40,7 @@ end
 for i=1:length(o.footnote)
     fprintf(fid, '\\blfootnote{\\tiny %d. %s}', i, o.footnote{i});
 end
-fprintf(fid,'\n');
+fprintf(fid, '\n');
 
 if ~isempty(o.latex)
     if ~exist(o.pageDirName, 'dir')
@@ -58,17 +58,16 @@ if ~isempty(o.latex)
     fprintf(fid, '\\input{%s}', pagename);
 else
     fprintf(fid, '\\begin{tabular}[t]{c}\n');
-    for i=1:length(o.title)
+    for i = 1:length(o.title)
         if isint(o.titleTruncate)
             if length(o.title{i}) > o.titleTruncate
                 o.title{i} = o.title{i}(1:o.titleTruncate);
             end
         end
-        fprintf(fid,'\\multicolumn{1}{c}{%s %s}\\\\\n', o.titleFormat{i}, o.title{i});
+        fprintf(fid, '\\multicolumn{1}{c}{%s %s}\\\\\n', o.titleFormat{i}, o.title{i});
     end
 
-    nps = length(o.sections);
-    for i=1:nps
+    for i = 1:length(o.sections)
         o.sections{i}.write(fid, pg, i);
     end
     fprintf(fid, '\\end{tabular}\n');
diff --git a/src/@paragraph/paragraph.m b/src/@paragraph/paragraph.m
index b01a0b1d58c0a7339256aee7d259f7596732d149..9220133de4ae195c7924a3cdabab557193270370 100644
--- a/src/@paragraph/paragraph.m
+++ b/src/@paragraph/paragraph.m
@@ -1,63 +1,82 @@
-function o = paragraph(varargin)
-%function o = paragraph(varargin)
-% Instantiates a paragraph object
-
-% Copyright (C) 2014-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-o = struct;
-
-o.balancedCols = false;
-o.cols = 1;
-o.heading = '';
-o.indent = true;
-o.text = '';
-
-if nargin == 1
-    assert(isa(varargin{1}, 'paragraph'),['With one arg to Paragraph constructor, ' ...
-                        'you must pass a paragraph object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@paragraph.paragraph: options must be supplied in name/value ' ...
-               'pairs.']);
+classdef paragraph < handle
+    % paragraph Class
+    %
+    % Copyright (C) 2014-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (SetAccess = private)
+        balancedCols = true % Determines whether the text is spread out evenly across the columns when the Paragraph has more than one column. Default: true.
+        cols = 1            % The number of columns for the Paragraph. Default: 1.
+        heading = ''        % The heading for the Paragraph (like a section heading). The string must be valid LATEX code. Default: empty.
+        indent = true       % Whether or not to indent the paragraph. Default: true.
+        text = ''           % The paragraph itself. The string must be valid LATEX code. Default: empty.
     end
+    methods
+        function o = paragraph(varargin)
+            %function o = paragraph(varargin)
+            % Paragraph Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty paragraph object
+            %                   1 arg   : must be paragraph object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [paragraph]  paragraph object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'paragraph'), ...
+                    'With one arg to Paragraph constructor, you must pass a paragraph object');
+                o = varargin{1};
+                return
+            end
+
+            if round(nargin/2) ~= nargin/2
+                error(['@paragraph.paragraph: options must be ' ...
+                    'supplied in name/value pairs.']);
+            end
 
-    optNames = fieldnames(o);
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@paragraph.paragraph: %s is not a recognized option.', pair{1});
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@paragraph.paragraph: %s is not a recognized option.', pair{1});
+                end
+            end
+            % Check input
+            assert(islogical(o.indent), '@paragraph.paragraph: indent must be either true or false');
+            assert(islogical(o.balancedCols), '@paragraph.paragraph: balancedCols must be either true or false');
+            assert(isint(o.cols), '@paragraph.paragraph: cols must be an integer');
+            assert(ischar(o.text), '@paragraph.paragraph: text must be a string');
+            assert(ischar(o.heading), '@paragraph.paragraph: heading must be a string');
         end
     end
-end
-
-assert(islogical(o.indent), '@paragraph.paragraph: indent must be either true or false');
-assert(islogical(o.balancedCols), '@paragraph.paragraph: balancedCols must be either true or false');
-assert(isint(o.cols), '@paragraph.paragraph: cols must be an integer');
-assert(ischar(o.text), '@paragraph.paragraph: text must be a string');
-assert(ischar(o.heading), '@paragraph.paragraph: heading must be a string');
-
-% Create paragraph object
-o = class(o, 'paragraph');
+    methods (Access = ?section, Hidden = true)
+        % Methods defined in separate files
+        write(o, fid);
+    end
 end
diff --git a/src/@paragraph/subsasgn.m b/src/@paragraph/subsasgn.m
deleted file mode 100644
index efd169d0a97e3b0d185c3dd93f58320aba9156e1..0000000000000000000000000000000000000000
--- a/src/@paragraph/subsasgn.m
+++ /dev/null
@@ -1,50 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2014-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B.elements{index} = V;
-  case '{}'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@paragraph.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@paragraph.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@paragraph/subsref.m b/src/@paragraph/subsref.m
deleted file mode 100644
index 92ddff6b546273a8e00c7c6697ebb1f2e813fece..0000000000000000000000000000000000000000
--- a/src/@paragraph/subsref.m
+++ /dev/null
@@ -1,48 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2014-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@paragraph.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    A = A.elements{S(1).subs{:}};
-  case '{}'
-    error(['@paragraph.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@paragraph.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@paragraph/write.m b/src/@paragraph/write.m
index 7f0b399b51393b5ae3ae01443ff8dc55e16ad9a3..a800438c9dcfcba4d14facf106bdaaa631e90592 100644
--- a/src/@paragraph/write.m
+++ b/src/@paragraph/write.m
@@ -1,5 +1,5 @@
-function o = write(o, fid)
-%function o = write(o, fid)
+function write(o, fid)
+%function write(o, fid)
 % Write Paragraph object
 %
 % INPUTS
diff --git a/src/@report/addData.m b/src/@report/addData.m
index 7559f2097581d5a423f451c72160147b7b3bc453..2ff066a55617bdafa5e0d7afe1d5139452c94ff8 100644
--- a/src/@report/addData.m
+++ b/src/@report/addData.m
@@ -1,10 +1,10 @@
 function o = addData(o, varargin)
 %function o = addData(o, varargin)
-% Add data to the current section of the current page in the report
+% Add data
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @report_table/addData
+%   varargin             arguments to report_data()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -29,17 +29,7 @@ function o = addData(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(~isempty(o.pages) , ...
-       ['@report.addData: Before adding data, you must add a page, ' ...
-        'section, and a table.']);
-assert(~isempty(o.pages{end}.sections) , ...
-       ['@report.addData: Before adding data, you must add a section and ' ...
-        'a table']);
-assert(~isempty(o.pages{end}.sections{end}.elements), ...
-       '@report.addData: Before adding data, you must add a table');
-assert(isa(o.pages{end}.sections{end}.elements{end}, 'report_table'), ...
-       '@report.addData: you can only add data to a report_table object');
-
-o.pages{end}.sections{end}.elements{end} = ...
-    o.pages{end}.sections{end}.elements{end}.addData(varargin{:});
+assert(~isempty(o.pages), ...
+       '@report.addData: Before adding data, you must add a page, section, and a table.');
+o.pages{end}.addData(varargin{:});
 end
diff --git a/src/@report/addGraph.m b/src/@report/addGraph.m
index 1c703a37b8a5398dbf3309c70454e55bafe9a4ad..7a4e68e48495b873c2cc8a1a725fc238a5f5a278 100644
--- a/src/@report/addGraph.m
+++ b/src/@report/addGraph.m
@@ -1,10 +1,10 @@
 function o = addGraph(o, varargin)
 %function o = addGraph(o, varargin)
-% Add a graph to the current section of the current page in the report
+% Add a graph
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @section/addGraph.m
+%   varargin             arguments to graph()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -12,7 +12,7 @@ function o = addGraph(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,10 +29,7 @@ function o = addGraph(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages) > 0, ...
        '@report.addGraph: Before adding a graph, you must add a page and a section.');
-assert(length(o.pages{end}.sections) > 0, ...
-       '@report.addGraph: Before adding a graph, you must add a section.');
-o.pages{end}.sections{end} = ...
-    o.pages{end}.sections{end}.addGraph(varargin{:});
+o.pages{end}.addGraph(varargin{:});
 end
diff --git a/src/@report/addPage.m b/src/@report/addPage.m
index 6f0e1ef772f37fbbcf2d7257d51bf3b65cce082f..8137962b6cea2553b7448597aaa4438e2029a1d9 100644
--- a/src/@report/addPage.m
+++ b/src/@report/addPage.m
@@ -1,6 +1,6 @@
 function o = addPage(o, varargin)
 %function o = addPage(o, varargin)
-% Add a page to the report
+% Add a page
 %
 % INPUTS
 %   o          [report]  report object
diff --git a/src/@report/addParagraph.m b/src/@report/addParagraph.m
index 56e605f53d2ad367759fb8f9b3679f614cdbf761..7dfd9478ac4ac65f9b0e3a5580e3b8e947050af0 100644
--- a/src/@report/addParagraph.m
+++ b/src/@report/addParagraph.m
@@ -1,10 +1,10 @@
 function o = addParagraph(o, varargin)
 %function o = addParagraph(o, varargin)
-% Add a paragraph to the current section of the current page in the report
+% Add a paragraph
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @section/addGraph.m
+%   varargin             arguments to paragraph()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -12,7 +12,7 @@ function o = addParagraph(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,10 +29,7 @@ function o = addParagraph(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages) > 0, ...
        '@report.addParagraph: Before adding a paragraph, you must add a page and a section.');
-assert(length(o.pages{end}.sections) > 0, ...
-       '@report.addParagraph: Before adding a paragraph, you must add a section.');
-o.pages{end}.sections{end} = ...
-    o.pages{end}.sections{end}.addParagraph(varargin{:});
+o.pages{end}.addParagraph(varargin{:});
 end
diff --git a/src/@report/addSection.m b/src/@report/addSection.m
index eec30fd5c882be575cd758ffdb40f47dcc60269d..430ec84f88661b613c488283f31e4ca42fec1aa8 100644
--- a/src/@report/addSection.m
+++ b/src/@report/addSection.m
@@ -1,10 +1,10 @@
 function o = addSection(o, varargin)
 %function o = addSection(o, varargin)
-% Add a section to the current page in the report
+% Add a section
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @section/addGraph.m
+%   varargin             arguments to section()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -12,7 +12,7 @@ function o = addSection(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,7 +29,7 @@ function o = addSection(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages) > 0, ...
        '@report.addSection: Before adding a section, you must add a page.');
-o.pages{end} = o.pages{end}.addSection(varargin{:});
+o.pages{end}.addSection(varargin{:});
 end
diff --git a/src/@report/addSeries.m b/src/@report/addSeries.m
index 064a2a82cd23571d0e315d7f37ce4310e8a195c2..239740e3cc0beabda8691351ae2a97b4bd0fc3fd 100644
--- a/src/@report/addSeries.m
+++ b/src/@report/addSeries.m
@@ -4,7 +4,7 @@ function o = addSeries(o, varargin)
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @graph/addSeries
+%   varargin             arguments to report_series()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -12,7 +12,7 @@ function o = addSeries(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,19 +29,8 @@ function o = addSeries(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages), ...
        ['@report.addSeries: Before adding a series, you must add a page, ' ...
         'section, and either a graph or a table.']);
-assert(length(o.pages{end}.sections) > 0, ...
-       ['@report.addSeries: Before adding a series, you must add a section and ' ...
-        'either a graph or a table']);
-assert(length(o.pages{end}.sections{end}.elements) > 0, ...
-       ['@report.addSeries: Before adding a series, you must add ' ...
-        'either a graph or a table']);
-assert(isa(o.pages{end}.sections{end}.elements{end}, 'graph') || ...
-       isa(o.pages{end}.sections{end}.elements{end}, 'report_table'), ...
-       '@report.addSeries: you can only add a series to a report_table or graph object');
-
-o.pages{end}.sections{end}.elements{end} = ...
-    o.pages{end}.sections{end}.elements{end}.addSeries(varargin{:});
+o.pages{end}.addSeries(varargin{:});
 end
diff --git a/src/@report/addTable.m b/src/@report/addTable.m
index 8a0e125301efa9dc6118f7a351f933e54eab475c..12e46216fbd264532dae35114c69c4b6cb2c8689 100644
--- a/src/@report/addTable.m
+++ b/src/@report/addTable.m
@@ -4,7 +4,7 @@ function o = addTable(o, varargin)
 %
 % INPUTS
 %   o          [report]  report object
-%   varargin             arguments to @section/addTable.m
+%   varargin             arguments to report_table()
 %
 % OUTPUTS
 %   o          [report]  updated report object
@@ -29,10 +29,7 @@ function o = addTable(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages), ...
        '@report.addTable: Before adding a table, you must add a page and a section.');
-assert(length(o.pages{end}.sections) > 0, ...
-       '@report.addTable: Before adding a table, you must add a section.');
-o.pages{end}.sections{end} = ...
-    o.pages{end}.sections{end}.addTable(varargin{:});
+o.pages{end}.addTable(varargin{:});
 end
diff --git a/src/@report/addVspace.m b/src/@report/addVspace.m
index 4e01c8626fcdb916278d05d8de3eb8b5774ee44e..f3fee71a49546c072bc0d1b5d6542cf562fb7a2b 100644
--- a/src/@report/addVspace.m
+++ b/src/@report/addVspace.m
@@ -12,7 +12,7 @@ function o = addVspace(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,10 +29,7 @@ function o = addVspace(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(length(o.pages) > 0, ...
+assert(~isempty(o.pages), ...
        '@report.addVspace: Before adding a vspace, you must add a page and a section.');
-assert(length(o.pages{end}.sections) > 0, ...
-       '@report.addVspace: Before adding a vspace, you must add a section.');
-o.pages{end}.sections{end} = ...
-    o.pages{end}.sections{end}.addVspace(varargin{:});
+o.pages{end}.addVspace(varargin{:});
 end
diff --git a/src/@report/report.m b/src/@report/report.m
index 813e81cacfa80de92453d944249b6c02e77e877d..7cac59d0450c1dfdcf52abbee0920864ba5fbc7f 100644
--- a/src/@report/report.m
+++ b/src/@report/report.m
@@ -1,94 +1,113 @@
-function o = report(varargin)
-%function o = report(varargin)
-% Report Class Constructor
-%
-% INPUTS
-%   varargin        0 args  : empty report object
-%                   1 arg   : must be report object (return a copy of arg)
-%                   > 1 args: option/value pairs (see structure below for options)
-%
-% OUTPUTS
-%   o     [report]  report object
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2016 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-% default values
-o = struct;
-o.title = '';
-o.orientation = 'portrait';
-o.paper = 'a4';
-o.margin = 2.5;
-o.marginUnit = 'cm';
-o.pages = {};
-o.fileName = 'report.tex';
-o.showDate = true;
-o.compiler = '';
-o.showOutput = true;
-o.header = '';
-
-if nargin == 1
-    assert(isa(varargin{1}, 'report'), ['@report.report: with one arg, ' ...
-                        'you must pass a report object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@report.report: options must be supplied in name/value ' ...
-               'pairs']);
+classdef report < handle
+    % report Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (Access = private)
+        pages = {}
     end
+    properties (SetAccess = private)
+        title = ''               % Report Title. Default: none.
+        orientation = 'portrait' % Paper orientation: Default: `portrait'.
+        paper = 'a4'             % Paper size. Default: `a4'.
+        margin = 2.5             % The margin size. Default: 2.5.
+        marginUnit = 'cm'        % Units associated with the margin. Default: `cm'.
+        fileName = 'report.tex'  % The file name to use when saving this report. Default: report.tex.
+        showDate = true          % Display the date and time when the report was compiled. Default: true.
+        compiler = ''            % The full path to the LATEX compiler on your system
+        showOutput = true        % Print report creation progress to screen. Shows you the page number as it is created and as it is written. This is useful to see where a potential error occurs in report creation. Default: true.
+        header = ''              % The valid LATEX code to be included in the report before \begin{document}. Default: empty.
+    end
+    methods
+        function o = report(varargin)
+            %function o = report(varargin)
+            % Report Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty report object
+            %                   1 arg   : must be report object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [report]  report object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'report'), ...
+                    '@report.report: with one arg, you must pass a report object');
+                o = varargin{1};
+                return
+            end
 
-    optNames = fieldnames(o);
+            if round(nargin/2) ~= nargin/2
+                error('@report.report: options must be supplied in name/value pairs');
+            end
 
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@report.report: %s is not a recognized option.', pair{1});
-        end
-    end
-end
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-% Check options provided by user
-assert(ischar(o.title), '@report.report: title must be a string');
-assert(ischar(o.fileName), '@report.report: fileName must be a string');
-assert(ischar(o.compiler), '@report.report: compiler file must be a string');
-assert(islogical(o.showDate), '@report.report: showDate must be either true or false');
-assert(islogical(o.showOutput), '@report.report: showOutput must be either true or false');
-assert(isfloat(o.margin) && o.margin > 0, '@report.report: margin must be a float > 0.');
-assert(ischar(o.header), '@report.report: header must be a string');
-valid_margin_unit = {'cm', 'in'};
-assert(any(strcmp(o.marginUnit, valid_margin_unit)), ...
-       ['@report.report: marginUnit must be one of ' addCommasToCellStr(valid_margin_unit)]);
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@report.report: %s is not a recognized option.', pair{1});
+                end
+            end
 
-valid_paper = {'a4', 'letter'};
-assert(any(strcmp(o.paper, valid_paper)), ...
-       ['@report.report: paper must be one of ' addCommasToCellStr(valid_paper)]);
+            % Check options provided by user
+            assert(ischar(o.title), '@report.report: title must be a string');
+            assert(ischar(o.fileName), '@report.report: fileName must be a string');
+            assert(ischar(o.compiler), '@report.report: compiler file must be a string');
+            assert(islogical(o.showDate), '@report.report: showDate must be either true or false');
+            assert(islogical(o.showOutput), '@report.report: showOutput must be either true or false');
+            assert(isfloat(o.margin) && o.margin > 0, '@report.report: margin must be a float > 0.');
+            assert(ischar(o.header), '@report.report: header must be a string');
+            valid_margin_unit = {'cm', 'in'};
+            assert(any(strcmp(o.marginUnit, valid_margin_unit)), ...
+                ['@report.report: marginUnit must be one of ' addCommasToCellStr(valid_margin_unit)]);
 
-valid_orientation = {'portrait', 'landscape'};
-assert(any(strcmp(o.orientation, valid_orientation)), ...
-       ['@report.report: orientation must be one of ' addCommasToCellStr(valid_orientation)]);
+            valid_paper = {'a4', 'letter'};
+            assert(any(strcmp(o.paper, valid_paper)), ...
+                ['@report.report: paper must be one of ' addCommasToCellStr(valid_paper)]);
 
-% Create report object
-o = class(o, 'report');
+            valid_orientation = {'portrait', 'landscape'};
+            assert(any(strcmp(o.orientation, valid_orientation)), ...
+                ['@report.report: orientation must be one of ' addCommasToCellStr(valid_orientation)]);
+        end
+        o = addPage(o, varargin)
+        o = addSection(o, varargin)
+        o = addGraph(o, varargin)
+        o = addTable(o, varargin)
+        o = addVspace(o, varargin)
+        o = addParagraph(o, varargin)
+        o = addSeries(o, varargin)
+        o = addData(o, varargin)
+        o = compile(o, varargin)
+        o = write(o)
+    end
+    methods (Hidden = true)
+        n = numPages(o)
+    end
 end
diff --git a/src/@report/subsasgn.m b/src/@report/subsasgn.m
deleted file mode 100644
index 75d54412e10bca44f4a943b9646afae62bb74bca..0000000000000000000000000000000000000000
--- a/src/@report/subsasgn.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B.pages{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@report.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@report.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@report/subsref.m b/src/@report/subsref.m
deleted file mode 100644
index 0c58e4bdbceabd9db8bd67138e31cda8609ea5e8..0000000000000000000000000000000000000000
--- a/src/@report/subsref.m
+++ /dev/null
@@ -1,48 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@report.subsasgn: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    A = A.pages{S(1).subs{:}};
-  case '{}'
-    error(['@report.subsasgn: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@report.subsasgn: impossible case');
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@report/write.m b/src/@report/write.m
index 168747b0e39713c046f99d54e4d6ec99b8efcf6e..063f8ee3a2b29c1110c4389b4c67011fbfcd08ae 100644
--- a/src/@report/write.m
+++ b/src/@report/write.m
@@ -84,8 +84,7 @@ end
 fprintf(fid, '\\pgfplotsset{tick scale binop={\\times},\ntrim axis left}\n');
 fprintf(fid, '\\centering\n');
 
-nps = length(o.pages);
-for i=1:nps
+for i = 1:length(o.pages)
     if o.showOutput
         fprintf(1, 'Writing Page: %d\n', i);
     end
diff --git a/src/@report_data/display.m b/src/@report_data/display.m
deleted file mode 100644
index 70978f668acdfb8791a048d6c05fb2e4bbecfcb9..0000000000000000000000000000000000000000
--- a/src/@report_data/display.m
+++ /dev/null
@@ -1,32 +0,0 @@
-function display(o)
-%function display(o)
-% Display a Report_Series object
-%
-% INPUTS
-%   o   [report_series] report_series object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-display_reporting_object(o);
-end
\ No newline at end of file
diff --git a/src/@report_data/printData.m b/src/@report_data/printData.m
index 9ee508fc511aa9e89f4ed8a028500c90e21f4719..f77c9bb2d4b12735b432ad983071a0bb30468228 100644
--- a/src/@report_data/printData.m
+++ b/src/@report_data/printData.m
@@ -1,4 +1,4 @@
-function o = printData(o, fid, data, precision)
+function printData(o, fid, data, precision)
 %function printData(o, fid, dser, precision)
 % function to print a row of data, contained in data
 %
diff --git a/src/@report_data/report_data.m b/src/@report_data/report_data.m
index 0edca41d0362a72dd63f57632e54b013b25dfbe7..622d418bd9a475edd3ac1957632cb37c3b522cf5 100644
--- a/src/@report_data/report_data.m
+++ b/src/@report_data/report_data.m
@@ -1,76 +1,80 @@
-function o = report_data(varargin)
-%function o = report_data(varargin)
-% Report_Data Class Constructor
-%
-% INPUTS
-%   varargin        0 args  : empty report_data object
-%                   1 arg   : must be report_data object (return a copy of arg)
-%                   > 1 args: option/value pairs (see structure below for
-%                   options)
-%
-% OUTPUTS
-%   o   [report_data] report_data object
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2019 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-o = struct;
-
-o.data = '';
-
-o.tableSubSectionHeader = '';
-o.tableAlignRight = false;
-
-o.tableRowColor = 'white';
-o.tableRowIndent = 0;
-
-o.tableNaNSymb = 'NaN';
-
-o.tablePrecision = '';
-
-o.zeroTol = 1e-6;
-
-if nargin == 1
-    assert(isa(varargin{1}, 'report_data'), ...
-        '@report_data.report_data: with one arg you must pass a report_data object');
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error('@report_data.report_data: options must be supplied in name/value pairs.');
+classdef report_data < handle
+    % report_data Class to write a page to the report
+    %
+    % Copyright (C) 2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (SetAccess = private)
+        data = ''
+        tableSubSectionHeader = ''
+        tableAlignRight = false
+        tableRowColor = 'white'
+        tableRowIndent = 0
+        tableNaNSymb = 'NaN'
+        tablePrecision = ''
+        zeroTol = 1e-6
     end
+    methods
+        function o = report_data(varargin)
+            %function o = report_data(varargin)
+            % report_data Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty report_data object
+            %                   1 arg   : must be report_data object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [report_data]  report_data object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'report_data'), ...
+                    '@report_data.report_data: with one arg you must pass a report_data object');
+                o = varargin{1};
+                return
+            end
+            if round(nargin/2) ~= nargin/2
+                error('@report_data.report_data: options must be supplied in name/value pairs.');
+            end
 
-    optNames = fieldnames(o);
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@report_data.report_data: %s is not a recognized option.', pair{1});
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@report_data.report_data: %s is not a recognized option.', pair{1});
+                end
+            end
         end
     end
-end
-
-% Create report_data object
-o = class(o, 'report_data');
+    methods (Access = ?report_table, Hidden = true)
+        writeDataForTable(o, fid, precision)
+    end
+    methods (Access = private)
+        printData(o, fid, data, precision)
+    end
 end
diff --git a/src/@report_data/subsasgn.m b/src/@report_data/subsasgn.m
deleted file mode 100644
index eebda6ef4f8dcf8256e7c7e9ac638721d31b1640..0000000000000000000000000000000000000000
--- a/src/@report_data/subsasgn.m
+++ /dev/null
@@ -1,42 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2019 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@report_data.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@report_data.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@report_data/subsref.m b/src/@report_data/subsref.m
deleted file mode 100644
index 1f887da2297b43e12afaaaf2d2abecc3674bcf89..0000000000000000000000000000000000000000
--- a/src/@report_data/subsref.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2019 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@report_data.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case {'()', '{}'}
-    error(['@report_data.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@report_data.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@report_data/writeDataForTable.m b/src/@report_data/writeDataForTable.m
index 8c50454531385a8ad9a3036cd578a81af497e5d7..109c48550d88795cac8cc88019f870c15827a5c8 100644
--- a/src/@report_data/writeDataForTable.m
+++ b/src/@report_data/writeDataForTable.m
@@ -1,5 +1,5 @@
-function o = writeDataForTable(o, fid, precision)
-%function o = writeDataForTable(o, fid, precision)
+function writeDataForTable(o, fid, precision)
+%function writeDataForTable(o, fid, precision)
 % Write Table Data
 %
 % INPUTS
diff --git a/src/@report_series/display.m b/src/@report_series/display.m
deleted file mode 100644
index 70978f668acdfb8791a048d6c05fb2e4bbecfcb9..0000000000000000000000000000000000000000
--- a/src/@report_series/display.m
+++ /dev/null
@@ -1,32 +0,0 @@
-function display(o)
-%function display(o)
-% Display a Report_Series object
-%
-% INPUTS
-%   o   [report_series] report_series object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-display_reporting_object(o);
-end
\ No newline at end of file
diff --git a/src/@report_series/report_series.m b/src/@report_series/report_series.m
index ba303e5a77a6fba8eea63f419071db5c2bb2c108..ff9375627cd4f4a1220b21d83fe6f4cf6994813a 100644
--- a/src/@report_series/report_series.m
+++ b/src/@report_series/report_series.m
@@ -1,113 +1,119 @@
-function o = report_series(varargin)
-%function o = report_series(varargin)
-% Report_Series Class Constructor
-%
-% INPUTS
-%   varargin        0 args  : empty report_series object
-%                   1 arg   : must be report_series object (return a copy of arg)
-%                   > 1 args: option/value pairs (see structure below for
-%                   options)
-%
-% OUTPUTS
-%   o   [report_series] report_series object
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-o = struct;
-
-o.data = '';
-
-o.graphFanShadeColor = '';
-o.graphFanShadeOpacity = 50;
-
-o.graphLegendName = '';
-
-o.graphLineColor = 'black';
-o.graphLineStyle = 'solid';
-o.graphLineWidth = 0.5;
-
-o.graphShowInLegend = true;
-
-o.graphMarker = '';
-o.graphMarkerEdgeColor = '';
-o.graphMarkerFaceColor = '';
-o.graphMarkerSize = 1;
-
-o.graphMiscTikzAddPlotOptions = '';
-
-o.graphHline = {};
-o.graphVline = dates();
-
-o.graphBar = false;
-o.graphBarColor = 'black';
-o.graphBarFillColor = 'black';
-o.graphBarWidth = 2;
-
-o.tableShowMarkers = false;
-o.tableNegColor = 'red';
-o.tablePosColor = 'blue';
-o.tableMarkerLimit = 1e-4;
-
-o.tableSubSectionHeader = '';
-o.tableAlignRight = false;
-
-o.tableRowColor = 'white';
-o.tableRowIndent = 0;
-
-o.tableDataRhs = '';
-o.tableNaNSymb = 'NaN';
-
-o.tablePrecision = '';
-
-o.zeroTol = 1e-6;
-
-if nargin == 1
-    assert(isa(varargin{1}, 'report_series'),['@report_series.report_series: with one arg you ' ...
-                        'must pass a report_series object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@report_series.report_series: options must be supplied in name/value ' ...
-               'pairs.']);
+classdef report_series < handle
+    % report_series Class to write a page to the report
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (SetAccess = private)
+        data = ''                        % The dseries that provides the data for the graph. Default: none.
+        graphFanShadeColor = ''          % The shading color to use between a series and the previously-added series in a graph. Useful for making fan charts. Default: empty.
+        graphFanShadeOpacity = 50        % The opacity of the color passed in graphFanShadeColor. Default: 50.
+        graphLegendName = ''             % The name to display in the legend for this series, passed as valid LATEX (e.g., GDP_{US}, $\alpha$, \color{red}GDP\color{black}). Will be displayed only if the data and showLegend options have been passed. Default: the tex name of the series.
+        graphLineColor = 'black'         % Color to use for the series in a graph. See the explanation in shadeColor for how to use colors with reports. Default: `black'
+        graphLineStyle = 'solid'         % Line style for this series in a graph. Default: `solid'.
+        graphLineWidth = 0.5             % Line width for this series in a graph. Default: 0.5.
+        graphShowInLegend = true         % Whether or not to show this series in the legend, given that the showLegend option was passed to addGraph. Default: true.
+        graphMarker = ''                 % The Marker to use on this series in a graph. Default: none.
+        graphMarkerEdgeColor = ''        % The edge color of the graph marker. See the explanation in shadeColor for how to use colors with reports. Default: graphLineColor.
+        graphMarkerFaceColor = ''        % The face color of the graph marker. See the explanation in shadeColor for how to use colors with reports. Default: graphLineColor.
+        graphMarkerSize = 1              % The size of the graph marker. Default: 1.
+        graphMiscTikzAddPlotOptions = '' % If you are comfortable with PGFPLOTS/TikZ, you can use this option to pass arguments di- rectly to the PGFPLOTS/TikZ addPlots command. (e.g., Instead of passing the marker options above, you can pass a string such as the following to this option: `mark=halfcircle*,mark options={rotate=90,scale=3}'). Specifically to be used for desired PGFPLOTS/TikZ options that have not been incorporated into Dynare Reproting. Default: empty.
+        graphHline = {}                  % Use this option to draw a horizontal line at the given value. Default: empty.
+        graphVline = dates()             % Use this option to draw a vertical line at a given date. Default: empty.
+        graphBar = false                 % Whether or not to display this series as a bar graph as oppsed to the default of displaying it as a line graph. Default: false.
+        graphBarColor = 'black'          % The outline color of each bar in the bar graph. Only active if graphBar is passed. Default: `black'.
+        graphBarFillColor = 'black'      % The fill color of each bar in the bar graph. Only active if graphBar is passed. Default: `black'.
+        graphBarWidth = 2                % The width of each bar in the bar graph. Only active if graphBar is passed. Default: 2.
+        tableShowMarkers = false         % In a Table, if true, surround each cell with brackets and color it according to tableNegColor and tablePosColor. No effect for graphs. Default: false.
+        tableNegColor = 'red'            % The color to use when marking Table data that is less than zero. Default: `red'
+        tablePosColor = 'blue'           % The color to use when marking Table data that is greater than zero. Default: `blue'
+        tableMarkerLimit = 1e-4          % For values less than ?1 * tableMarkerLimit, mark the cell with the color denoted by tableNeg- Color. For those greater than tableMarkerLimit, mark the cell with the color denoted by table- PosColor. Default: 1e-4.
+        tableSubSectionHeader = ''       % A header for a subsection of the table. No data will be associated with it. It is equivalent to adding an empty series with a name. Default: ''
+        tableAlignRight = false          % Whether or not to align the series name to the right of the cell. Default: false.
+        tableRowColor = 'white'          % The color that you want the row to be. Predefined values include LightCyan and Gray. Default: white.
+        tableRowIndent = 0               % The number of times to indent the name of the series in the table. Used to create subgroups of series. Default: 0.
+        tableDataRhs = ''                % A series to be added to the right of the current series. Usefull for displaying aggregate data for a series. e.g if the series is quarterly tableDataRhs could point to the yearly averages of the quarterly series. This would cause quarterly data to be displayed followed by annual data. Default: empty.
+        tableNaNSymb = 'NaN'             % Replace NaN values with the text in this option. Default: NaN.
+        tablePrecision = ''              % The number of decimal places to report in the table data. Default: the value set by precision.
+        zeroTol = 1e-6                   % The zero tolerance. Anything smaller than zeroTol and larger than -zeroTol will be set to zero before being graphed or written to the table. Default: 1e-6.
     end
-
-    optNames = fieldnames(o);
-
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@report_series.report_series: %s is not a recognized option.', pair{1});
+    methods
+        function o = report_series(varargin)
+            %function o = report_series(varargin)
+            % Report_Series Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty report_series object
+            %                   1 arg   : must be report_series object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [report_series]  report_series object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'report_series'), ...
+                    '@report_series.report_series: with one arg you must pass a report_series object');
+                o = varargin{1};
+                return
+            end
+
+            if round(nargin/2) ~= nargin/2
+                error('@report_series.report_series: options must be supplied in name/value pairs.');
+            end
+
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
+
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@report_series.report_series: %s is not a recognized option.', pair{1});
+                end
+            end
+            if ~isempty(o.graphLegendName)
+                o.data = o.data.tex_rename(o.graphLegendName);
+            end
         end
     end
-end
-
-if ~isempty(o.graphLegendName)
-    o.data = o.data.tex_rename(o.graphLegendName);
-end
-
-% Create report_series object
-o = class(o, 'report_series');
+    methods (Access = ?graph, Hidden = true)
+        s = getNameForLegend(o)
+        writeSeriesForGraph(o, fid, xrange, series_num)
+    end
+    methods (Access = ?report_table, Hidden = true)
+        writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
+    end
+    methods (Access = {?graph,?report_table}, Hidden = true)
+        tf = isZero(o)
+    end
+    methods (Access = private)
+        dd = getRange(o)
+        s = getTexName(o)
+        o = printSeries(o, fid, dser, dates, precision)
+        d = setDataToZeroFromZeroTol(o, ds)
+        ymax = ymax(o, dd)
+        ymin = ymin(o, dd)
+    end
 end
diff --git a/src/@report_series/subsasgn.m b/src/@report_series/subsasgn.m
deleted file mode 100644
index ceb8dc6b80a5776bf17bd5e308a7a4f29e26bd12..0000000000000000000000000000000000000000
--- a/src/@report_series/subsasgn.m
+++ /dev/null
@@ -1,42 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@report_series.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@report_series.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@report_series/subsref.m b/src/@report_series/subsref.m
deleted file mode 100644
index 8c235bd7a455a5b60ed62e16fa7ea848146b75d9..0000000000000000000000000000000000000000
--- a/src/@report_series/subsref.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@report_series.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case {'()', '{}'}
-    error(['@report_series.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@report_series.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@report_series/writeSeriesForGraph.m b/src/@report_series/writeSeriesForGraph.m
index d87ca279fead6827083825e941846e3922a4d957..ee2bd94347a9c8906ec870a133c368780a302c56 100644
--- a/src/@report_series/writeSeriesForGraph.m
+++ b/src/@report_series/writeSeriesForGraph.m
@@ -1,11 +1,11 @@
-function o = writeSeriesForGraph(o, fid, xrange, series_num)
-%function o = writeSeriesForGraph(o, fid, xrange, series_num)
+function writeSeriesForGraph(o, fid, xrange, series_num)
+%function writeSeriesForGraph(o, fid, xrange, series_num)
 % Print a TikZ line
 %
 % INPUTS
-%   o       [report_series]    series object
-%   xrange  [dates]            range of x values for line
-%   series_num [int]           the number of this series in the total number of series passed to this graph
+%   o          [report_series]    series object
+%   xrange     [dates]            range of x values for line
+%   series_num [int]              the number of this series in the total number of series passed to this graph
 %
 % OUTPUTS
 %   NONE
@@ -13,7 +13,7 @@ function o = writeSeriesForGraph(o, fid, xrange, series_num)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2014-2017 Dynare Team
+% Copyright (C) 2014-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
diff --git a/src/@report_series/writeSeriesForTable.m b/src/@report_series/writeSeriesForTable.m
index de78c10cdfe9a4204ff94bfc0c8ce5d28fbbda23..f6e4d256e1371e4d86c3b2911ec6b72902234ccc 100644
--- a/src/@report_series/writeSeriesForTable.m
+++ b/src/@report_series/writeSeriesForTable.m
@@ -1,5 +1,5 @@
-function o = writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
-%function o = writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
+function writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
+%function writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
 % Write Table Row
 %
 % INPUTS
@@ -17,7 +17,7 @@ function o = writeSeriesForTable(o, fid, dates, precision, ncols, rowcolor)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2017 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
diff --git a/src/@report_table/addData.m b/src/@report_table/addData.m
index e095799318278425cce824827d29c6e11e1a2494..9bb66c8894fc17f1b35f35dde7131b88eed09765 100644
--- a/src/@report_table/addData.m
+++ b/src/@report_table/addData.m
@@ -1,5 +1,16 @@
 function o = addData(o, varargin)
-% function o = addData(o, varargin)
+%function o = addData(o, varargin)
+% Add a series
+%
+% INPUTS
+%   o          [report_table] report_table object
+%   varargin                  arguments to report_data()
+%
+% OUTPUTS
+%   updated section object
+%
+% SPECIAL REQUIREMENTS
+%   none
 
 % Copyright (C) 2019 Dynare Team
 %
diff --git a/src/@report_table/addSeries.m b/src/@report_table/addSeries.m
index 971e0ebb009dadedf619f77a3d1f5496739f9df5..348aa785bd99e6c33cd9ade8ce58c9841f3d93c1 100644
--- a/src/@report_table/addSeries.m
+++ b/src/@report_table/addSeries.m
@@ -1,7 +1,18 @@
 function o = addSeries(o, varargin)
-% function o = addSeries(o, varargin)
+%function o = addSeries(o, varargin)
+% Add a series
+%
+% INPUTS
+%   o          [report_table] report_table object
+%   varargin                  arguments to report_series()
+%
+% OUTPUTS
+%   updated section object
+%
+% SPECIAL REQUIREMENTS
+%   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
diff --git a/src/@report_table/display.m b/src/@report_table/display.m
deleted file mode 100644
index 84c436c31840f5c3f21ee19e47d608b58c1b94e8..0000000000000000000000000000000000000000
--- a/src/@report_table/display.m
+++ /dev/null
@@ -1,32 +0,0 @@
-function display(o)
-%function display(o)
-% Display a Report_Table object
-%
-% INPUTS
-%   o   [report_table] report_table object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-display_reporting_object(o);
-end
\ No newline at end of file
diff --git a/src/@report_table/report_table.m b/src/@report_table/report_table.m
index a800cf5b849bfac654de8b69ce7b56cd55afd364..085501112f0c0b1a77aa6caa416c8af70c63b8db 100644
--- a/src/@report_table/report_table.m
+++ b/src/@report_table/report_table.m
@@ -1,18 +1,182 @@
-function o = report_table(varargin)
-%function o = report_table(varargin)
-% Report_Table Class Constructor
+classdef report_table < handle
+    % report_table Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (Access = private, Constant = true)
+        titleFormatDefalut = {'\large'}
+    end
+    properties (Access = private)
+        series = {}
+        table_data = {}
+        % Not documented
+        preamble = {''}
+        afterward = {''}
+        column_names = ''
+    end
+    properties (SetAccess = private)
+        tableDirName = 'tmpRepDir'    % The name of the folder in which to store this table. Default: tmpRepDir.
+        tableName = ''                % The name to use when saving this table. Default: something of the form table_pg1_sec2_row1_col3.tex.
+        title = {''}                  % Table Title. Default: none.
+        titleFormat = ''              % A string representing the valid LATEX markup to use on title. The number of cell array entries must be equal to that of the title option if you do not want to use the default value for the title (and subtitles). Default: \large\bfseries.
+        showHlines = false            % Whether or not to show horizontal lines separating the rows. Default: false.
+        showVlines = false            %
+        vlineAfter = ''               % Show a vertical line after the specified date (or dates if a cell array of dates is passed). Default: empty.
+        vlineAfterEndOfPeriod = false % Show a vertical line after the end of every period (i.e. after every year, after the fourth quarter, etc.). Default: false.
+        data = ''                     % The dseries that provides the data for the graph. Default: none.
+        seriesToUse = ''              % The names of the series contained in the dseries provided to the data option. If empty, use all series provided to data option. Default: empty.
+        range = {}                    % The date range of the data to be displayed. Default: all.
+        precision = 1                 % The number of decimal places to report in the table data (rounding done via the round half away from zero method). Default: 1.
+        writeCSV = false              % Whether or not to write a CSV file containing the data displayed in the table. The file will be saved in the directory specified by tableDirName with the same base name as specified by tableName with the ending .csv. Default: false.
+        highlightRows = {''}          % A cell array containing the colors to use for row highlighting. See shadeColor for how to use colors with reports. Highlighting for a specific row can be overridden by using the tableRowColor option to addSeries. Default: empty.
+    end
+    methods (Access = ?section)
+        function o = report_table(varargin)
+            %function o = report_table(varargin)
+            % Report_Table Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty report_table object
+            %                   1 arg   : must be report_table object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [report_table]  report_table object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            o.titleFormat = o.titleFormatDefalut;
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'report_table'), ...
+                    'With one arg to the Report_Table constructor, you must pass a report_table object');
+                o = varargin{1};
+                return
+            end
+
+            if round(nargin/2) ~= nargin/2
+                error('Options to Report_Table constructor must be supplied in name/value pairs.');
+            end
+
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
+
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('%s is not a recognized option to the Report_Table constructor.', pair{1});
+                end
+            end
+
+            if ~iscell(o.range)
+                o.range = {o.range};
+            end
+
+            if isdates(o.vlineAfter)
+                o.vlineAfter = {o.vlineAfter};
+            end
+
+            % Check options provided by user
+            if ischar(o.title)
+                o.title = {o.title};
+            end
+
+            if ischar(o.titleFormat)
+                o.titleFormat = {o.titleFormat};
+            end
+            if length(o.title) ~= length(o.titleFormat)
+                o.titleFormat = repmat(o.titleFormatDefalut, 1, length(o.title));
+            end
+            assert(islogical(o.showHlines), '@report_table.report_table: showHlines must be true or false');
+            assert(islogical(o.showVlines), '@report_table.report_table: showVlines must be true or false');
+            assert(isint(o.precision) && o.precision >= 0, '@report_table.report_table: precision must be a non-negative integer');
+            assert(isempty(o.range) || length(o.range) <=2 && allCellsAreDatesRange(o.range), ...
+                ['@report_table.report_table: range is specified as a dates range, e.g. ' ...
+                '''dates(''1999q1''):dates(''1999q3'')''.']);
+            assert(isempty(o.data) || isdseries(o.data), ...
+                '@report_table.report_table: data must be a dseries');
+            assert(isempty(o.seriesToUse) || iscellstr(o.seriesToUse), ...
+                '@report_table.report_table: seriesToUse must be a cell array of string(s)');
+            assert(isempty(o.vlineAfter) || allCellsAreDates(o.vlineAfter), ...
+                '@report_table.report_table: vlineAfter must be a dates');
+            if o.showVlines
+                o.vlineAfter = '';
+            end
+            assert(islogical(o.vlineAfterEndOfPeriod), ...
+                '@report_table.report_table: vlineAfterEndOfPeriod must be true or false');
+            assert(iscellstr(o.title), ...
+                '@report_table.report_table: title must be a cell array of string(s)');
+            assert(iscellstr(o.titleFormat), ...
+                '@report_table.report_table: titleFormat must be a cell array of string(s)');
+            assert(ischar(o.tableName), '@report_table.report_table: tableName must be a string');
+            assert(ischar(o.tableDirName), '@report_table.report_table: tableDirName must be a string');
+            assert(islogical(o.writeCSV), '@report_table.report_table: writeCSV must be either true or false');
+            assert(iscellstr(o.highlightRows), '@report_table.report_table: highlightRowsmust be a cell string');
+
+            % using o.seriesToUse, create series objects and put them in o.series
+            if ~isempty(o.data)
+                if isempty(o.seriesToUse)
+                    for i=1:o.data.vobs
+                        o.series{end+1} = report_series('data', o.data{o.data.name{i}});
+                    end
+                else
+                    for i=1:length(o.seriesToUse)
+                        o.series{end+1} = report_series('data', o.data{o.seriesToUse{i}});
+                    end
+                end
+            end
+            o.data = '';
+            o.seriesToUse = '';
+            if ~exist(o.tableDirName, 'file')
+                mkdir(o.tableDirName);
+            end
+        end
+    end
+    methods (Access = ?section, Hidden = true)
+        o = addData(o, varargin)
+        o = addSeries(o, varargin)
+        write(o, fid, pg, sec, row, col)
+    end
+    methods (Access = private)
+        o = writeTableFile(o, pg, sec, row, col)
+    end
+end
+
+function tf = allCellsAreDatesRange(dcell)
+%function tf = allCellsAreDatesRange(dcell)
+% Determines if all the elements of dcell are a range of dates
 %
 % INPUTS
-%   0 args => empty report_table
-%   1 arg (report_table class) => copy object
+%   dcell     cell of dates
 %
 % OUTPUTS
-%   none
+%   tf        true if every entry of dcell is a range of dates
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2019 Dynare Team
+% Copyright (C) 2014-2015 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -29,123 +193,52 @@ function o = report_table(varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-o = struct;
-
-o.tableDirName = 'tmpRepDir';
-o.tableName = '';
-
-o.series = {};
-
-o.title = {''};
-titleFormatDefalut = {'\large'};
-o.titleFormat = titleFormatDefalut;
-
-o.showHlines = false;
-o.showVlines = false;
-o.vlineAfter = '';
-o.vlineAfterEndOfPeriod = false;
-
-o.data = '';
-o.seriesToUse = '';
-o.range = {};
-o.precision = 1;
-o.writeCSV = false;
-
-o.highlightRows = {''};
-
-o.preamble = {''};
-o.afterward = {''};
-o.column_names = '';
-o.table_data = {};
-
-if nargin == 1
-    assert(isa(varargin{1}, 'report_table'),['With one arg to Report_Table constructor, ' ...
-                        'you must pass a report_table object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['Options to Report_Table constructor must be supplied in name/value ' ...
-               'pairs.']);
+assert(iscell(dcell));
+tf = true;
+for i=1:length(dcell)
+    if ~(isdates(dcell{i}) && dcell{i}.ndat >= 2)
+        tf = false;
+        return;
     end
-
-    optNames = fieldnames(o);
-
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('%s is not a recognized option to the Report_Table constructor.', pair{1});
-        end
-    end
-end
-if ~iscell(o.range)
-    o.range = {o.range};
 end
-
-if isdates(o.vlineAfter)
-    o.vlineAfter = {o.vlineAfter};
 end
 
-% Check options provided by user
-if ischar(o.title)
-    o.title = {o.title};
-end
+function tf = allCellsAreDates(dcell)
+%function tf = allCellsAreDates(dcell)
+% Determines if all the elements of dcell are dates objects
+%
+% INPUTS
+%   dcell     cell of dates objects
+%
+% OUTPUTS
+%   tf        true if every entry of dcell is a dates object
+%
+% SPECIAL REQUIREMENTS
+%   none
 
-if ischar(o.titleFormat)
-    o.titleFormat = {o.titleFormat};
-end
-if length(o.title) ~= length(o.titleFormat)
-    o.titleFormat = repmat(titleFormatDefalut, 1, length(o.title));
-end
-assert(islogical(o.showHlines), '@report_table.report_table: showHlines must be true or false');
-assert(islogical(o.showVlines), '@report_table.report_table: showVlines must be true or false');
-assert(isint(o.precision) && o.precision >= 0, '@report_table.report_table: precision must be a non-negative integer');
-assert(isempty(o.range) || length(o.range) <=2 && allCellsAreDatesRange(o.range), ...
-       ['@report_table.report_table: range is specified as a dates range, e.g. ' ...
-        '''dates(''1999q1''):dates(''1999q3'')''.']);
-assert(isempty(o.data) || isdseries(o.data), ...
-       '@report_table.report_table: data must be a dseries');
-assert(isempty(o.seriesToUse) || iscellstr(o.seriesToUse), ...
-       '@report_table.report_table: seriesToUse must be a cell array of string(s)');
-assert(isempty(o.vlineAfter) || allCellsAreDates(o.vlineAfter), ...
-       '@report_table.report_table: vlineAfter must be a dates');
-if o.showVlines
-    o.vlineAfter = '';
-end
-assert(islogical(o.vlineAfterEndOfPeriod), ...
-       '@report_table.report_table: vlineAfterEndOfPeriod must be true or false');
-assert(iscellstr(o.title), ...
-       '@report_table.report_table: title must be a cell array of string(s)');
-assert(iscellstr(o.titleFormat), ...
-       '@report_table.report_table: titleFormat must be a cell array of string(s)');
-assert(ischar(o.tableName), '@report_table.report_table: tableName must be a string');
-assert(ischar(o.tableDirName), '@report_table.report_table: tableDirName must be a string');
-assert(islogical(o.writeCSV), '@report_table.report_table: writeCSV must be either true or false');
-assert(iscellstr(o.highlightRows), '@report_table.report_table: highlightRowsmust be a cell string');
+% Copyright (C) 2014-2015 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-% using o.seriesToUse, create series objects and put them in o.series
-if ~isempty(o.data)
-    if isempty(o.seriesToUse)
-        for i=1:o.data.vobs
-            o.series{end+1} = report_series('data', o.data{o.data.name{i}});
-        end
-    else
-        for i=1:length(o.seriesToUse)
-            o.series{end+1} = report_series('data', o.data{o.seriesToUse{i}});
-        end
+assert(iscell(dcell));
+tf = true;
+for i=1:length(dcell)
+    if ~isdates(dcell{i})
+        tf = false;
+        return;
     end
 end
-o = rmfield(o, 'seriesToUse');
-o = rmfield(o, 'data');
-
-if ~exist(o.tableDirName, 'file')
-    mkdir(o.tableDirName);
 end
-
-% Create report_table object
-o = class(o, 'report_table');
-end
\ No newline at end of file
diff --git a/src/@report_table/subsasgn.m b/src/@report_table/subsasgn.m
deleted file mode 100644
index 574be0f0590a6cb3547ff1276234429cf08b4729..0000000000000000000000000000000000000000
--- a/src/@report_table/subsasgn.m
+++ /dev/null
@@ -1,45 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@report_table.subsasgn: field ' S.subs 'does not exist in the report_table class'])
-    end
-  case '{}'
-    assert(isint(S.subs{1}));
-    B{S.subs{1}} = V;
-  otherwise
-    error('@report_table.subsasgn: syntax error')
-end
-end
\ No newline at end of file
diff --git a/src/@report_table/subsref.m b/src/@report_table/subsref.m
deleted file mode 100644
index 49d7e6a6eb53953ca57adc86e2260b1ac9d5f149..0000000000000000000000000000000000000000
--- a/src/@report_table/subsref.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@report_table.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case {'()', '{}'}
-    error(['@report_table.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@report_table.subsref: subsref.m impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@report_table/write.m b/src/@report_table/write.m
index ab6b061009c29ef6c00a4590e84f89eea5133665..2e51b752c01e555dcd3f58fe52bb7b0d657dd394 100644
--- a/src/@report_table/write.m
+++ b/src/@report_table/write.m
@@ -1,5 +1,5 @@
-function o = write(o, fid, pg, sec, row, col)
-%function o = write(o, fid, pg, sec, row, col)
+function write(o, fid, pg, sec, row, col)
+%function write(o, fid, pg, sec, row, col)
 % Write a Table object
 %
 % INPUTS
@@ -16,7 +16,7 @@ function o = write(o, fid, pg, sec, row, col)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -34,6 +34,6 @@ function o = write(o, fid, pg, sec, row, col)
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 assert(fid ~= -1);
-o = writeTableFile(o, pg, sec, row, col);
-fprintf(fid, '\\input{%s}', o.tableName);
+tableName = writeTableFile(o, pg, sec, row, col);
+fprintf(fid, '\\input{%s}', tableName);
 end
diff --git a/src/@report_table/writeTableFile.m b/src/@report_table/writeTableFile.m
index 78348d98669960a84d263ba25f5b5a0c2464cd65..2c9b21d3110df1f653fe9a7c2e08cbd2181251c4 100644
--- a/src/@report_table/writeTableFile.m
+++ b/src/@report_table/writeTableFile.m
@@ -1,5 +1,5 @@
-function o = writeTableFile(o, pg, sec, row, col)
-%function o = writeTableFile(o, pg, sec, row, col)
+function tableName = writeTableFile(o, pg, sec, row, col)
+%function tableName = writeTableFile(o, pg, sec, row, col)
 % Write a Report_Table object
 %
 % INPUTS
@@ -10,7 +10,7 @@ function o = writeTableFile(o, pg, sec, row, col)
 %   col [integer] this col number
 %
 % OUTPUTS
-%   o   [report_table]    report_table object
+%   tableName   [string]    name of table written
 %
 % SPECIAL REQUIREMENTS
 %   none
@@ -36,16 +36,16 @@ ne = length(o.series);
 is_data_table = ~isempty(o.table_data);
 if ne == 0 && ~is_data_table
     warning('@report_table.write: no series to plot, returning');
-    return;
+    return
 end
 
 if isempty(o.tableName)
-    o.tableName = sprintf('%s/table_pg%d_sec%d_row%d_col%d.tex', o.tableDirName, pg, sec, row, col);
+    tableName = sprintf('%s/table_pg%d_sec%d_row%d_col%d.tex', o.tableDirName, pg, sec, row, col);
 else
-    o.tableName = [o.tableDirName '/' o.tableName];
+    tableName = [o.tableDirName '/' o.tableName];
 end
 
-[fid, msg] = fopen(o.tableName, 'w');
+[fid, msg] = fopen(tableName, 'w');
 if fid == -1
     error(['@report_table.writeTableFile: ' msg]);
 end
@@ -60,7 +60,6 @@ fprintf(fid, '\\setlength{\\tabcolsep}{4pt}\n');
 %         GDP Germany
 % this example would be two lh columns, with GDP Europe spanning both
 nlhc = 1;
-
 if ~is_data_table
     fprintf(fid, '\\begin{tabular}{@{}l');
     if isempty(o.range)
diff --git a/src/allCellsAreDatesRange.m b/src/@section/addData.m
similarity index 52%
rename from src/allCellsAreDatesRange.m
rename to src/@section/addData.m
index 592ccf1219278d0db7884bb1b66c012eb4e047ca..8d4b91d55b452a28b66cb4486b679c3debab66dc 100644
--- a/src/allCellsAreDatesRange.m
+++ b/src/@section/addData.m
@@ -1,17 +1,18 @@
-function tf = allCellsAreDatesRange(dcell)
-%function tf = allCellsAreDatesRange(dcell)
-% Determines if all the elements of dcell are a range of dates
+function o = addData(o, varargin)
+%function o = addData(o, varargin)
+% Add a series
 %
 % INPUTS
-%   dcell     cell of dates
+%   o          [section] section object
+%   varargin             arguments to report_series()
 %
 % OUTPUTS
-%   tf        true if every entry of dcell is a range of dates
+%   updated section object
 %
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2014-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -28,12 +29,11 @@ function tf = allCellsAreDatesRange(dcell)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-assert(iscell(dcell));
-tf = true;
-for i=1:length(dcell)
-    if ~(isdates(dcell{i}) && dcell{i}.ndat >= 2)
-        tf = false;
-        return;
-    end
+assert(~isempty(o.elements), ...
+    '@section.addData: Before adding data, you must add either a table');
+assert(~isa(o.elements{1}, 'paragraph'), ...
+    '@section.addSeries: A section that contains a paragraph cannot contain a graph or a table');
+assert(isa(o.elements{end}, 'report_table'), ...
+    '@report.addData: you can only add data to a report_table object');
+o.elements{end}.addData(varargin{:});
 end
-end
\ No newline at end of file
diff --git a/src/@section/addGraph.m b/src/@section/addGraph.m
index 8f7ce1b0d13055eb2236ed54d7fa2dea9f997fa5..dd794930fb05eb28e1ee22e22b63cc4f2f289289 100644
--- a/src/@section/addGraph.m
+++ b/src/@section/addGraph.m
@@ -1,11 +1,10 @@
 function o = addGraph(o, varargin)
 %function o = addGraph(o, varargin)
-% Add a graph to the Cell Array of graphs in the report
+% Add a graph
 %
 % INPUTS
-%   1 args => add empty graph
-%   2 args => add given graph
-%   3 args => add graph at index
+%   o          [section] section object
+%   varargin             arguments to graph()
 %
 % OUTPUTS
 %   updated section object
@@ -13,7 +12,7 @@ function o = addGraph(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -30,9 +29,9 @@ function o = addGraph(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-for i=1:length(o.elements)
-    assert(~isa(o.elements{i}, 'paragraph'), ...
-           '@addGraph: A Section that contains a Paragraph cannot contain a Graph');
+if ~isempty(o.elements)
+    assert(~isa(o.elements{1}, 'paragraph'), ...
+        '@section.addSeries: A section that contains a paragraph cannot contain a graph or a table');
 end
 o.elements{end+1} = graph(varargin{:});
 end
diff --git a/src/@section/addParagraph.m b/src/@section/addParagraph.m
index e678c17992b00eded122792038c8c6e8abb6612e..49cbe50441819e57fae5fbe31e9bc8132d027bd7 100644
--- a/src/@section/addParagraph.m
+++ b/src/@section/addParagraph.m
@@ -1,11 +1,10 @@
 function o = addParagraph(o, varargin)
 %function o = addParagraph(o, varargin)
-% Add a paragraph to the Cell Array of elements in this section
+% Add a paragraph
 %
 % INPUTS
-%   1 args => add empty paragraph
-%   2 args => add given paragraph
-%   3 args => add paragraph at index
+%   o          [section] section object
+%   varargin             arguments to paragraph()
 %
 % OUTPUTS
 %   updated page object
@@ -13,7 +12,7 @@ function o = addParagraph(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2014-2017 Dynare Team
+% Copyright (C) 2014-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -31,12 +30,10 @@ function o = addParagraph(o, varargin)
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 assert(o.cols == 1, ...
-       ['@addParagraph: you can only add a paragraph to a Section that ' ...
-        'contains one column']);
-for i=1:length(o.elements)
+       '@addParagraph: you can only add a paragraph to a Section that contains one column');
+for i = 1:length(o.elements)
     assert(isa(o.elements{i}, 'paragraph'), ...
-           ['@addParagraph: you can only add a paragraph to a Section that ' ...
-            'contains only paragraphs']);
+           '@addParagraph: you can only add a paragraph to a Section that contains only paragraphs');
 end
 o.elements{end+1} = paragraph(varargin{:});
 end
diff --git a/src/@section/addSeries.m b/src/@section/addSeries.m
new file mode 100644
index 0000000000000000000000000000000000000000..8418e667257dbacbbac7a45e11ca589a3c225f97
--- /dev/null
+++ b/src/@section/addSeries.m
@@ -0,0 +1,39 @@
+function o = addSeries(o, varargin)
+%function o = addSeries(o, varargin)
+% Add a series
+%
+% INPUTS
+%   o          [section] section object
+%   varargin             arguments to report_series()
+%
+% OUTPUTS
+%   updated section object
+%
+% SPECIAL REQUIREMENTS
+%   none
+
+% Copyright (C) 2013-2019 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+
+assert(~isempty(o.elements), ...
+    '@section.addSeries: Before adding a series, you must add either a graph or a table');
+assert(~isa(o.elements{1}, 'paragraph'), ...
+    '@section.addSeries: A section that contains a paragraph cannot contain a graph or a table');
+assert(isa(o.elements{end}, 'graph') || isa(o.elements{end}, 'report_table'), ...
+    '@report.addSeries: you can only add a series to a report_table or graph object');
+o.elements{end}.addSeries(varargin{:});
+end
diff --git a/src/@section/addTable.m b/src/@section/addTable.m
index ea69e8db307f60daa6cf5d38a469674800af93b0..7b819d760a69f30e981e06040585ae1a9d28ad3a 100644
--- a/src/@section/addTable.m
+++ b/src/@section/addTable.m
@@ -1,11 +1,10 @@
 function o = addTable(o, varargin)
 %function o = addTable(o, varargin)
-% Add a report_table to the Cell Array of report_tables in the report
+% Add a report_table
 %
 % INPUTS
-%   1 args => add empty report_table
-%   2 args => add given report_table
-%   3 args => add report_table at index
+%   o          [section] section object
+%   varargin             arguments to report_table()
 %
 % OUTPUTS
 %   updated section object
@@ -13,7 +12,7 @@ function o = addTable(o, varargin)
 % SPECIAL REQUIREMENTS
 %   none
 
-% Copyright (C) 2013-2015 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -30,9 +29,9 @@ function o = addTable(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-for i=1:length(o.elements)
-    assert(~isa(o.elements{i}, 'paragraph'), ...
-           '@addTable: A Section that contains a Paratable cannot contain a Table');
+if ~isempty(o.elements)
+    assert(~isa(o.elements{1}, 'paragraph'), ...
+        '@section.addSeries: A section that contains a paragraph cannot contain a graph or a table');
 end
 o.elements{end+1} = report_table(varargin{:});
 end
diff --git a/src/@section/addVspace.m b/src/@section/addVspace.m
index 543205ae9ab37fd04003efb0a900ee86f9dea6e2..7bd48428ba106f5af9953b5021ffac4757a572b9 100644
--- a/src/@section/addVspace.m
+++ b/src/@section/addVspace.m
@@ -1,10 +1,10 @@
 function o = addVspace(o, varargin)
 %function o = addVspace(o, varargin)
-% Add a vspace to the Cell Array of vspaces in the report
+% Add a vspace
 %
 % INPUTS
-%   1 args => add empty vspace
-%   2 args => add given vspace
+%   o          [section] section object
+%   varargin             arguments to vspace()
 %
 % OUTPUTS
 %   updated section object
@@ -29,9 +29,9 @@ function o = addVspace(o, varargin)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-for i=1:length(o.elements)
-    assert(~isa(o.elements{i}, 'paragraph'), ...
-           '@addVspace: A Section that contains a Paragraph cannot contain a Vspace');
+if ~isempty(o.elements)
+    assert(~isa(o.elements{1}, 'paragraph'), ...
+        '@section.addSeries: A section that contains a paragraph cannot contain a graph or a table');
 end
 o.elements{end+1} = vspace(varargin{:});
 end
diff --git a/src/@section/display.m b/src/@section/display.m
deleted file mode 100644
index 51400d472764d3f33f928b3ffe70c360014f9924..0000000000000000000000000000000000000000
--- a/src/@section/display.m
+++ /dev/null
@@ -1,32 +0,0 @@
-function display(o)
-%function display(o)
-% Display a Section object
-%
-% INPUTS
-%   o   [section] section object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-display_reporting_object(o);
-end
\ No newline at end of file
diff --git a/src/@section/section.m b/src/@section/section.m
index 3270fe58429771b6556a2af17e5ac3f93dc8693d..59ba9f1b9687ebd669c90737c3e6e2d33bfcedd7 100644
--- a/src/@section/section.m
+++ b/src/@section/section.m
@@ -1,60 +1,86 @@
-function o = section(varargin)
-%function o = section(varargin)
-
-% Section produces a latex minipage
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+classdef section < handle
+    % section Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (Access = private)
+        elements = {}
+    end
+    properties (SetAccess = private)
+        cols = 1    % The number of columns in the section. Default: 1.
+        height = '' % A string to be used with the \sectionheight LATEX command. Default: '!'
+    end
+    methods (Access = ?page)
+        function o = section(varargin)
+            %function o = section(varargin)
+            % Section Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty section object
+            %                   1 arg   : must be section object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [section]  section object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'section'), ...
+                    'With one arg to Section constructor, you must pass a section object');
+                o = varargin{1};
+                return
+            end
 
-o = struct;
-o.elements = {};
-o.cols = 1;
-o.height = '';
+            if round(nargin/2) ~= nargin/2
+                error('@section.section: options must be supplied in name/value pairs.');
+            end
 
-if nargin == 1
-    assert(isa(varargin{1}, 'section'),['With one arg to Section constructor, ' ...
-                        'you must pass a section object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@section.section: options must be supplied in name/value ' ...
-               'pairs.']);
-    end
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-    optNames = fieldnames(o);
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@section.section: %s is not a recognized option.', pair{1});
+                end
+            end
 
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@section.section: %s is not a recognized option.', pair{1});
+            % Check options provided by user
+            assert(isint(o.cols), '@section.section: cols must be an integer');
+            assert(isempty(o.height) || ischar(o.height), ...
+                '@section.section: cols must be a string');
         end
     end
-end
-
-% Check options provided by user
-assert(isint(o.cols), '@section.section: cols must be an integer');
-assert(isempty(o.height) || ischar(o.height), ...
-       '@section.section: cols must be a string');
-
-% Create section object
-o = class(o, 'section');
+    methods (Access = ?page, Hidden = true)
+         o = addGraph(o, varargin)
+         o = addParagraph(o, varargin)
+         o = addTable(o, varargin)
+         o = addVspace(o, varargin)
+         lastIndex = end(o, k, n)
+         n = numElements(o)
+         write(o, fid, pg, sec)
+    end
 end
diff --git a/src/@section/subsasgn.m b/src/@section/subsasgn.m
deleted file mode 100644
index 14f8f802613270e04dfbe7f77797db15ccd5e7bf..0000000000000000000000000000000000000000
--- a/src/@section/subsasgn.m
+++ /dev/null
@@ -1,50 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B.elements{index} = V;
-  case '{}'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@section.subsasgn: field ' S.subs 'does not exist']);
-    end
-  otherwise
-    error('@section.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@section/subsref.m b/src/@section/subsref.m
deleted file mode 100644
index d1f2e39ab440ac127ff1362f704d69ec235ad250..0000000000000000000000000000000000000000
--- a/src/@section/subsref.m
+++ /dev/null
@@ -1,48 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@section.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    A = A.elements{S(1).subs{:}};
-  case '{}'
-    error(['@section.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@section.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@section/write.m b/src/@section/write.m
index eadb35c097f7dc4f0eead5b976bc47cd75b04201..b2509971c2f60a89cd34655612d392f82dbc2abd 100644
--- a/src/@section/write.m
+++ b/src/@section/write.m
@@ -1,5 +1,5 @@
-function o = write(o, fid, pg, sec)
-%function o = write(o, fid, pg, sec)
+function write(o, fid, pg, sec)
+%function write(o, fid, pg, sec)
 % Write Section object
 %
 % INPUTS
@@ -71,7 +71,7 @@ for i=1:ne
         if col ~= o.cols
             fprintf(fid, '\\end{tabular}}\\\\\n');
             fprintf(fid, '%% End Section Object\n\n');
-            return;
+            return
         end
     else
         if isa(o.elements{i}, 'paragraph')
diff --git a/src/@vspace/display.m b/src/@vspace/display.m
deleted file mode 100644
index f9aa32b1dc89a322680dccee8f682da34feff280..0000000000000000000000000000000000000000
--- a/src/@vspace/display.m
+++ /dev/null
@@ -1,32 +0,0 @@
-function display(o)
-%function display(o)
-% Display a Vspace object
-%
-% INPUTS
-%   o   [vspace] vspace object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-display_reporting_object(o);
-end
\ No newline at end of file
diff --git a/src/@vspace/subsasgn.m b/src/@vspace/subsasgn.m
deleted file mode 100644
index c4b774f9014e9560861f42c4a5e3c0387c2d247d..0000000000000000000000000000000000000000
--- a/src/@vspace/subsasgn.m
+++ /dev/null
@@ -1,49 +0,0 @@
-function B = subsasgn(A, S, V)
-% function B = subsasgn(A, S, V)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-B = A;
-if length(S) > 1
-    for i=1:(length(S)-1)
-        B = subsref(B, S(i));
-    end
-    B = subsasgn(B, S(end), V);
-    B = subsasgn(A, S(1:(end-1)), B);
-    return
-end
-
-switch S.type
-  case '()'
-    index = S.subs{:};
-    assert(isnumeric(index));
-    B{index} = V;
-  case '.'
-    switch S.subs
-      case fieldnames(A)
-        B.(S.subs) = V;
-      otherwise
-        error(['@vspace.subsasgn: field ' S.subs 'does not exist']);
-    end
-  case '{}'
-    assert(isint(S.subs{1}));
-    B{S.subs{1}} = V;
-  otherwise
-    error('@vspace.subsasgn: syntax error');
-end
-end
\ No newline at end of file
diff --git a/src/@vspace/subsref.m b/src/@vspace/subsref.m
deleted file mode 100644
index 71c29d1161b8d12040426a5373fa743f8c73fa43..0000000000000000000000000000000000000000
--- a/src/@vspace/subsref.m
+++ /dev/null
@@ -1,48 +0,0 @@
-function A = subsref(A, S)
-%function A = subsref(A, S)
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-switch S(1).type
-  case '.'
-    switch S(1).subs
-      case fieldnames(A)
-        A = A.(S(1).subs);
-      case methods(A)
-            if areParensNext(S)
-                A = feval(S(1).subs, A, S(2).subs{:});
-                S = shiftS(S,1);
-            else
-                A = feval(S(1).subs, A);
-            end
-      otherwise
-        error(['@vspace.subsref: unknown field or method: ' S(1).subs]);
-    end
-  case '()'
-    A = getSections(A, S(1).subs{:});
-  case '{}'
-    error(['@vspace.subsref: ' S(1).type ' indexing not supported.']);
-  otherwise
-    error('@vspace.subsref: impossible case')
-end
-
-S = shiftS(S,1);
-if length(S) >= 1
-    A = subsref(A, S);
-end
-end
diff --git a/src/@vspace/vspace.m b/src/@vspace/vspace.m
index 27b5452dcb7fdac6a36b270b317103c2fc7ca7f7..375e1e167df2336331cf891c5a31a6a9a1113d30 100644
--- a/src/@vspace/vspace.m
+++ b/src/@vspace/vspace.m
@@ -1,67 +1,77 @@
-function o = vspace(varargin)
-%function o = vspace(varargin)
-% Vspace Class Constructor
-%
-% INPUTS
-%   0 args => empty vspace
-%   1 arg (vspace class) => copy object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+classdef vspace < handle
+    % vspace Class
+    %
+    % Copyright (C) 2013-2019 Dynare Team
+    %
+    % This file is part of Dynare.
+    %
+    % Dynare is free software: you can redistribute it and/or modify
+    % it under the terms of the GNU General Public License as published by
+    % the Free Software Foundation, either version 3 of the License, or
+    % (at your option) any later version.
+    %
+    % Dynare is distributed in the hope that it will be useful,
+    % but WITHOUT ANY WARRANTY; without even the implied warranty of
+    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    % GNU General Public License for more details.
+    %
+    % You should have received a copy of the GNU General Public License
+    % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+    properties (SetAccess = private)
+        hline = 0  % Number of horizontal lines to be inserted. Default 0
+        number = 1 % Number of new lines to be inserted. Default 1
+    end
+    methods (Access = ?section)
+        function o = vspace(varargin)
+            %function o = vspace(varargin)
+            % Vspace Class Constructor
+            %
+            % INPUTS
+            %   varargin        0 args  : empty vspace object
+            %                   1 arg   : must be vspace object (return a copy of arg)
+            %                   > 1 args: option/value pairs (see structure below for options)
+            %
+            % OUTPUTS
+            %   o     [vspace]  vspace object
+            %
+            % SPECIAL REQUIREMENTS
+            %   none
+            if nargin == 0
+                return
+            elseif nargin == 1
+                assert(isa(varargin{1}, 'vspace'), ...
+                    '@vspace.vspace: with one arg to Vspace constructor, you must pass a vspace object');
+                o = varargin{1};
+                return
+            end
 
-o = struct;
-o.number = 1;
-o.hline = 0;
+            if round(nargin/2) ~= nargin/2
+                error('@vspace.vspace: options must be supplied in name/value pairs.');
+            end
 
-if nargin == 1
-    assert(isa(varargin{1}, 'vspace'), ['@vspace.vspace: with one arg to Vspace ' ...
-                        'constructor, you must pass a vspace object']);
-    o = varargin{1};
-    return;
-elseif nargin > 1
-    if round(nargin/2) ~= nargin/2
-        error(['@vspace.vspace: options must be supplied in name/value ' ...
-               'pairs.']);
-    end
+            % Octave 5.1.0 has not implemented `properties` and issues a warning when using `fieldnames`
+            warning('off')
+            optNames = fieldnames(o);
+            warning('on')
 
-    optNames = fieldnames(o);
+            % overwrite default values
+            for pair = reshape(varargin, 2, [])
+                ind = find(strcmpi(optNames, pair{1}));
+                assert(isempty(ind) || length(ind) == 1);
+                if ~isempty(ind)
+                    o.(optNames{ind}) = pair{2};
+                else
+                    error('@vspace.vspace: %s is not a recognized option.', pair{1});
+                end
+            end
 
-    % overwrite default values
-    for pair = reshape(varargin, 2, [])
-        ind = find(strcmpi(optNames, pair{1}));
-        assert(isempty(ind) || length(ind) == 1);
-        if ~isempty(ind)
-            o.(optNames{ind}) = pair{2};
-        else
-            error('@vspace.vspace: %s is not a recognized option.', pair{1});
+            % Check options provided by user
+            assert(isint(o.number), '@vspace.vspace: number must be an integer');
+            assert(isint(o.hline), '@vspace.vspace: hline must be an integer');
         end
     end
-end
-
-% Check options provided by user
-assert(isint(o.number), '@vspace.vspace: number must be an integer');
-assert(isint(o.hline), '@vspace.vspace: hline must be an integer');
-
-% Create vspace object
-o = class(o, 'vspace');
+    methods (Access = ?section, Hidden = true)
+        % Methods defined in separate files
+        write(o, fid);
+    end
 end
diff --git a/src/areParensNext.m b/src/areParensNext.m
deleted file mode 100644
index 359980f606a214d4dd6818aa871daba917fc5975..0000000000000000000000000000000000000000
--- a/src/areParensNext.m
+++ /dev/null
@@ -1,26 +0,0 @@
-function tf = areParensNext(S)
-%function tf = areParensNext(S)
-
-% Copyright (C) 2013-2015 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-if length(S) > 1 && strcmp(S(2).type, '()')
-    tf = true;
-else
-    tf = false;
-end
-end
\ No newline at end of file
diff --git a/src/display_reporting_object.m b/src/display_reporting_object.m
deleted file mode 100644
index 33cea3fc9e64367925368416c833e46b50c6559b..0000000000000000000000000000000000000000
--- a/src/display_reporting_object.m
+++ /dev/null
@@ -1,95 +0,0 @@
-function display_reporting_object(o)
-%function display_reporting_object(o)
-% Display a Reporting Object
-%   i.e., one of: graph
-%                 page
-%                 report
-%                 report_series
-%                 report_table
-%                 section
-%                 vspace
-%
-% INPUTS
-%   o   [object] reporting object
-%
-% OUTPUTS
-%   none
-%
-% SPECIAL REQUIREMENTS
-%   none
-
-% Copyright (C) 2013-2017 Dynare Team
-%
-% This file is part of Dynare.
-%
-% Dynare is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Dynare is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
-
-fprintf('\n%s Object = \n\n', upper(class(o)));
-fields = fieldnames(o);
-for i=1:length(fields)
-    fprintf('    %s: ', fields{i});
-    val = o.(fields{i});
-    if iscell(val)
-        fprintf('{');
-        for j=1:length(val)
-            if ischar(val{j});
-                fprintf('''%s''', val{j});
-                if j~=length(val)
-                    fprintf(', ');
-                end
-            else
-                if strcmp(fields{i}, 'pages') || strcmp(fields{i}, 'sections')
-                    fprintf('%d', length(val));
-                    break;
-                else
-                    fprintf('fix this');
-                end
-            end
-        end
-        fprintf('}');
-    elseif ischar(val)
-        fprintf('''%s''', val);
-    elseif isnumeric(val)
-        fprintf('%s', num2str(val));
-    elseif islogical(val)
-        if val
-            fprintf('true');
-        else
-            fprintf('false');
-        end
-    elseif isobject(val)
-        if isdates(val)
-            if isempty(val)
-                fprintf('<dates: empty>');
-            else
-                fprintf('<dates: %s, ..., %s>', ...
-                        date2string(val(1)), date2string(val(end)));
-            end
-        elseif isdseries(val)
-            if numel(val) == 1
-                fprintf('<dseries: %s>', val.name{1});
-            else
-                fprintf('%s', class(val));
-            end
-        else
-            cl = class(val);
-            fprintf('%d', val.(['num' upper(cl(1)) cl(2:end)]));
-        end
-    else
-        fprintf('fix this');
-    end
-    fprintf('\n');
-end
-fprintf('\n');
-end
\ No newline at end of file
diff --git a/src/initialize_reporting_toolbox.m b/src/initialize_reporting_toolbox.m
new file mode 100644
index 0000000000000000000000000000000000000000..e51c565866c5f5615f63d64eafe0b1b4d3709fe1
--- /dev/null
+++ b/src/initialize_reporting_toolbox.m
@@ -0,0 +1,28 @@
+function initialize_reporting_toolbox()
+%function initialize_reporting_toolbox()
+%
+% Function to set the necessary paths for the Reporting toolbox
+%
+% Copyright (C) 2015-2019 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+
+% Find reporting source directory
+reporting_src_root = strrep(which('initialize_reporting_toolbox'), 'initialize_reporting_toolbox.m', '');
+
+% Add path to reporting source
+addpath([reporting_src_root filesep '..' filesep 'macros']);
+end
diff --git a/test/AnnualTable.m b/test/AnnualTable.m
index 77843619baf40b25bfc9277bac7e71c1bc599789..5c04370b13f6201b3272c4268a832dcb85a1c6a2 100644
--- a/test/AnnualTable.m
+++ b/test/AnnualTable.m
@@ -1,5 +1,5 @@
 function rep = AnnualTable(rep, db_a, dc_a, seriesRootName, arange)
-% Copyright (C) 2013-2017 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -18,17 +18,17 @@ function rep = AnnualTable(rep, db_a, dc_a, seriesRootName, arange)
 
 shortNames = {'US', 'EU', 'JA', 'EA6', 'LA6', 'RC6'};
 longNames  = {'Coca Cola', 'Kinder Bueno', 'Pizza', ...
-              'Vegetarianism Is Good', 'OS X', 'Dothraki'};
+    'Vegetarianism Is Good', 'OS X', 'Dothraki'};
 
-rep = rep.addSeries('tableSubSectionHeader', 'A group', ...
-                    'tableRowColor', 'red!22');
-for i=1:length(shortNames)
+rep.addSeries('tableSubSectionHeader', 'A group', ...
+    'tableRowColor', 'red!22');
+for i = 1:length(shortNames)
     db_a = db_a.tex_rename([seriesRootName shortNames{i}], longNames{i});
-    rep = rep.addSeries('data', db_a{[seriesRootName shortNames{i}]});
+    rep.addSeries('data', db_a{[seriesRootName shortNames{i}]});
     delta = dc_a{[seriesRootName shortNames{i}]}-db_a{[seriesRootName shortNames{i}]};
     delta = delta.tex_rename('$\Delta$');
-    rep = rep.addSeries('data', delta, ...
-                        'tableShowMarkers', true, ...
-                        'tableAlignRight', true);
+    rep.addSeries('data', delta, ...
+        'tableShowMarkers', true, ...
+        'tableAlignRight', true);
+end
 end
-end
\ No newline at end of file
diff --git a/test/CommResidTablePage.m b/test/CommResidTablePage.m
index f9a2247b5ccfa5ed7f58046a978ad529fe764cef..144c89d654407c1794fdbcb8d299390452187ce3 100644
--- a/test/CommResidTablePage.m
+++ b/test/CommResidTablePage.m
@@ -1,5 +1,5 @@
 function rep = CommResidTablePage(rep, db_q, dc_q, trange, vline_after)
-% Copyright (C) 2013-2017 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -17,22 +17,22 @@ function rep = CommResidTablePage(rep, db_q, dc_q, trange, vline_after)
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 seriesNames = {{'RES_LRPOIL_GAP_WORLD'}, ...
-               {'RES_LRPOIL_BAR_WORLD'}, ...
-               {'RES_LRPOIL_G_WORLD'}, ...
-               {'RES_LRPFOOD_GAP_WORLD'}, ...
-               {'RES_LRPFOOD_BAR_WORLD'}, ...
-               {'RES_LRPFOOD_G_WORLD'}};
+    {'RES_LRPOIL_BAR_WORLD'}, ...
+    {'RES_LRPOIL_G_WORLD'}, ...
+    {'RES_LRPFOOD_GAP_WORLD'}, ...
+    {'RES_LRPFOOD_BAR_WORLD'}, ...
+    {'RES_LRPFOOD_G_WORLD'}};
 
-rep = rep.addTable('title', 'Commodities', ...
-                   'range', trange, ...
-                   'vlineAfter', vline_after);
+rep.addTable('title', 'Commodities', ...
+    'range', trange, ...
+    'vlineAfter', vline_after);
 
-for i=1:length(seriesNames)
-    rep = rep.addSeries('data', db_q{seriesNames{i}{1}});
+for i = 1:length(seriesNames)
+    rep.addSeries('data', db_q{seriesNames{i}{1}});
     delta = db_q{seriesNames{i}{1}} - dc_q{seriesNames{i}{1}};
     delta = delta.tex_rename('$\Delta$');
-    rep = rep.addSeries('data', delta, ...
-                        'tableShowMarkers', true, ...
-                        'tableAlignRight', true);
+    rep.addSeries('data', delta, ...
+        'tableShowMarkers', true, ...
+        'tableAlignRight', true);
 end
 end
diff --git a/test/CountryGraphPage.m b/test/CountryGraphPage.m
index 8f352729d26610a76af1c4dea4f2a192eabdac70..549f828e0b42aeba9564e61129fc59851fc32640 100644
--- a/test/CountryGraphPage.m
+++ b/test/CountryGraphPage.m
@@ -1,5 +1,5 @@
 function rep = CountryGraphPage(rep, countryAbbr, db_q, dc_q, prange, srange)
-% Copyright (C) 2013-2017 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -19,95 +19,95 @@ function rep = CountryGraphPage(rep, countryAbbr, db_q, dc_q, prange, srange)
 startpoint = strings(prange(1));
 shaded = strings(srange(1));
 endpoint = strings(prange(end));
-rep = rep.addGraph('title', 'Interest Rate', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0, ...
-                   'writeCSV', true);
-rep = rep.addSeries('data', db_q{['RS_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['RS_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'Interest Rate', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0, ...
+    'writeCSV', true);
+rep.addSeries('data', db_q{['RS_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['RS_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'Output Gap', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{['Y_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['Y_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'Output Gap', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0);
+rep.addSeries('data', db_q{['Y_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['Y_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'Headline Inflation (y/y)', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{['PCH_PIE4_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['PCH_PIE4_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'Headline Inflation (y/y)', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0);
+rep.addSeries('data', db_q{['PCH_PIE4_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['PCH_PIE4_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'Headline Inflation (q/q)', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{['PCH_PIE_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['PCH_PIE_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'Headline Inflation (q/q)', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0);
+rep.addSeries('data', db_q{['PCH_PIE_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['PCH_PIE_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'GDP Growth (q/q)', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{['PCH_GROWTH_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['PCH_GROWTH_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'GDP Growth (q/q)', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0);
+rep.addSeries('data', db_q{['PCH_GROWTH_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['PCH_GROWTH_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'Core Inflation (y/y)', ...
-                   'titleFormat', '\Huge', ...
-                   'xrange', prange, ...
-                   'shade', srange, ...
-                   'showZeroline', true, ...
-                   'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
-                   'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
-                   'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{['PCH_PIEX4_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineStyle', 'dashed', ...
-                    'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{['PCH_PIEX4_' countryAbbr]}, ...
-                    'graphLineColor', 'blue', ...
-                    'graphLineWidth', 1.5);
+rep.addGraph('title', 'Core Inflation (y/y)', ...
+    'titleFormat', '\Huge', ...
+    'xrange', prange, ...
+    'shade', srange, ...
+    'showZeroline', true, ...
+    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
+    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
+    'xTickLabelRotation', 0);
+rep.addSeries('data', db_q{['PCH_PIEX4_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineStyle', 'dashed', ...
+    'graphLineWidth', 1.5);
+rep.addSeries('data', dc_q{['PCH_PIEX4_' countryAbbr]}, ...
+    'graphLineColor', 'blue', ...
+    'graphLineWidth', 1.5);
 end
\ No newline at end of file
diff --git a/test/CountryTablePage.m b/test/CountryTablePage.m
index 486608a135ce8f302cafbec566c2c4bc324ef99a..1b47f11c9bb0de64f57e4f2bdf7163bc3e4f4b15 100644
--- a/test/CountryTablePage.m
+++ b/test/CountryTablePage.m
@@ -1,5 +1,5 @@
 function rep = CountryTablePage(rep, countryAbbr, countryName, db_q, dc_q, db_a, dc_a, trange, vline_after)
-% Copyright (C) 2013-2017 Dynare Team
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -17,54 +17,52 @@ function rep = CountryTablePage(rep, countryAbbr, countryName, db_q, dc_q, db_a,
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 seriesNames = {{'RS_', 'Short Term Interest Rate'}, ...
-               {'RR_', 'Real Interest Rate'}, ...
-               {'BLT_','Bank Lending Tightening' }, ...
-               {'PCH_GROWTH_', 'Real GDP Growth (@q ar)'}, ...
-               {'PCH_GROWTH4_', '\% y-o-y'}, ...
-               {'PCH_GROWTH_BAR_', 'Potential GDP Growth (@q ar)'}, ...
-               {'PCH_GROWTH4_BAR_', '\% y-o-y'}, ...
-               {'PCH_PIE_', 'Headline CPI Inflation (@q ar)'}, ...
-               {'PCH_PIE4_', '\% y-o-y'}, ...
-               {'PCH_PIEX_', 'Core CPI Inflation (@q ar)'}, ...
-               {'PCH_PIEX4_', '\% y-o-y'}, ...
-               {'PCH_PIE_GAS_', 'Gas Inflation (@q ar)'}, ...
-               {'PCH_PIE4_GAS_', '\% y-o-y'}, ...
-               {'PCH_PIE_CONSFOOD_', 'Food Inflation (@q ar)'}, ...
-               {'PCH_PIE4_CONSFOOD_', '\% y-o-y'}, ...
-               {'PCH_DOT_REER_T_', 'REER Depreciation (@q ar)'}, ...
-               {'PCH_DOT4_REER_T_', '\% y-o-y'}, ...
-               {'Y_', 'Output Gap'}, ...
-               {'UNR_', 'Unemployment Rate'}, ...
-               {'UNR_BAR_', 'NAIRU'}, ...
-               {'UNR_GAP_', 'Unemployment Gap'}};
+    {'RR_', 'Real Interest Rate'}, ...
+    {'BLT_','Bank Lending Tightening' }, ...
+    {'PCH_GROWTH_', 'Real GDP Growth (@q ar)'}, ...
+    {'PCH_GROWTH4_', '\% y-o-y'}, ...
+    {'PCH_GROWTH_BAR_', 'Potential GDP Growth (@q ar)'}, ...
+    {'PCH_GROWTH4_BAR_', '\% y-o-y'}, ...
+    {'PCH_PIE_', 'Headline CPI Inflation (@q ar)'}, ...
+    {'PCH_PIE4_', '\% y-o-y'}, ...
+    {'PCH_PIEX_', 'Core CPI Inflation (@q ar)'}, ...
+    {'PCH_PIEX4_', '\% y-o-y'}, ...
+    {'PCH_PIE_GAS_', 'Gas Inflation (@q ar)'}, ...
+    {'PCH_PIE4_GAS_', '\% y-o-y'}, ...
+    {'PCH_PIE_CONSFOOD_', 'Food Inflation (@q ar)'}, ...
+    {'PCH_PIE4_CONSFOOD_', '\% y-o-y'}, ...
+    {'PCH_DOT_REER_T_', 'REER Depreciation (@q ar)'}, ...
+    {'PCH_DOT4_REER_T_', '\% y-o-y'}, ...
+    {'Y_', 'Output Gap'}, ...
+    {'UNR_', 'Unemployment Rate'}, ...
+    {'UNR_BAR_', 'NAIRU'}, ...
+    {'UNR_GAP_', 'Unemployment Gap'}};
 
 otherThree = {'EA6','LA6','RC6'};
 notForOtherThree = {'BLT_', 'UNR_', 'UNR_BAR_', 'UNR_GAP_'};
 
-rep = rep.addTable('title', countryName, ...
-                   'range', {trange, dates('2012a'):dates('2014a')}, ...
-                   'vlineAfter', {vline_after dates('2014q4')}, ...
-                   'writeCSV', true, ...
-                   'highlightRows', {'gray!22', 'cyan!33', 'blue!44', 'red!55'});
+rep.addTable('title', countryName, ...
+    'range', {trange, dates('2012a'):dates('2014a')}, ...
+    'vlineAfter', {vline_after dates('2014q4')}, ...
+    'writeCSV', true, ...
+    'highlightRows', {'gray!22', 'cyan!33', 'blue!44', 'red!55'});
 
-
-
-for i=1:length(seriesNames)
+for i = 1:length(seriesNames)
     if any(strcmp(countryAbbr, otherThree)) && ...
             any(strcmp(seriesNames{i}{1}, notForOtherThree))
         continue
     end
     db_q = db_q.tex_rename([seriesNames{i}{1} countryAbbr], seriesNames{i}{2});
-    rep = rep.addSeries('data', db_q{[seriesNames{i}{1} countryAbbr]}, ...
-                        'tableDataRhs', db_a{[seriesNames{i}{1} countryAbbr]});
+    rep.addSeries('data', db_q{[seriesNames{i}{1} countryAbbr]}, ...
+        'tableDataRhs', db_a{[seriesNames{i}{1} countryAbbr]});
     delta = db_q{[seriesNames{i}{1} countryAbbr]}-dc_q{[seriesNames{i}{1} countryAbbr]};
     delta = delta.tex_rename('$\Delta$');
-
+    
     deltaa = db_a{[seriesNames{i}{1} countryAbbr]}-dc_a{[seriesNames{i}{1} countryAbbr]};
     deltaa = deltaa.tex_rename('$\Delta$');
-    rep = rep.addSeries('data', delta, ...
-                        'tableShowMarkers', true, ...
-                        'tableRowIndent', 2, ...
-                        'tableDataRhs', deltaa);
+    rep.addSeries('data', delta, ...
+        'tableShowMarkers', true, ...
+        'tableRowIndent', 2, ...
+        'tableDataRhs', deltaa);
 end
 end
diff --git a/test/ResidTablePage.m b/test/ResidTablePage.m
index eb521de6c50bd9a316d66c77fe583097d7ada480..fee665cf6cb7f1a130f9bfbf8be8043ea71dbf0b 100644
--- a/test/ResidTablePage.m
+++ b/test/ResidTablePage.m
@@ -1,5 +1,5 @@
 function rep = ResidTablePage(rep, countryAbbr, countryName, db_q, dc_q, trange, vline_after)
-% Copyright (C) 2011-2017 Dynare Team
+% Copyright (C) 2011-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -17,24 +17,24 @@ function rep = ResidTablePage(rep, countryAbbr, countryName, db_q, dc_q, trange,
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 seriesNames = {{'RES_RS_'}, ...
-               {'RES_RR_BAR_'}, ...
-               {'RES_BLT_'}, ...
-               {'RES_BLT_BAR_'}, ...
-               {'RES_YY_'}, ...
-               {'RES_Y_'}, ...
-               {'RES_LGDP_BAR_'}, ...
-               {'RES_G_'}, ...
-               {'RES_UNR_GAP_'}, ...
-               {'RES_UNR_G_'}, ...
-               {'RES_UNR_BAR_'}, ...
-               {'RES_RR_DIFF_'}, ...
-               {'RES_LZ_BAR_'}, ...
-               {'RES_DOT_LZ_BAR_'}, ...
-               {'RES_PIETAR_'}, ...
-               {'RES_PIE_'}, ...
-               {'RES_PIEX_'}, ...
-               {'RES_PIE_GAS_'}, ...
-               {'RES_PIE_CONSFOOD_'}};
+    {'RES_RR_BAR_'}, ...
+    {'RES_BLT_'}, ...
+    {'RES_BLT_BAR_'}, ...
+    {'RES_YY_'}, ...
+    {'RES_Y_'}, ...
+    {'RES_LGDP_BAR_'}, ...
+    {'RES_G_'}, ...
+    {'RES_UNR_GAP_'}, ...
+    {'RES_UNR_G_'}, ...
+    {'RES_UNR_BAR_'}, ...
+    {'RES_RR_DIFF_'}, ...
+    {'RES_LZ_BAR_'}, ...
+    {'RES_DOT_LZ_BAR_'}, ...
+    {'RES_PIETAR_'}, ...
+    {'RES_PIE_'}, ...
+    {'RES_PIEX_'}, ...
+    {'RES_PIE_GAS_'}, ...
+    {'RES_PIE_CONSFOOD_'}};
 
 otherThree = {'EA6', 'LA6', 'RC6'};
 notForOtherThree = {'RES_BLT_', 'RES_BLT_BAR_', 'RES_UNR_GAP_', 'RES_UNR_G_', 'RES_UNR_BAR_'};
@@ -44,22 +44,22 @@ notForUS = {'RES_RR_DIFF_', 'RES_LZ_BAR_'};
 firstThree = {'US', 'EU', 'JA'};
 notForFirstThree = {'RES_DOT_LZ_BAR_', 'RES_PIETAR_'};
 
-rep = rep.addTable('title', countryName, ...
-                   'range', trange, ...
-                   'vlineAfter', vline_after);
+rep.addTable('title', countryName, ...
+    'range', trange, ...
+    'vlineAfter', vline_after);
 
 for i=1:length(seriesNames)
     if (any(strcmp(countryAbbr, otherThree)) && ...
-        any(strcmp(seriesNames{i}{1}, notForOtherThree))) || ...
+            any(strcmp(seriesNames{i}{1}, notForOtherThree))) || ...
             (any(strcmp(countryAbbr, 'US')) && any(strcmp(seriesNames{i}{1}, notForUS))) || ...
             (any(strcmp(countryAbbr, firstThree)) && any(strcmp(seriesNames{i}{1}, notForFirstThree)))
         continue
     end
-    rep = rep.addSeries('data', db_q{[seriesNames{i}{1} countryAbbr]});
+    rep.addSeries('data', db_q{[seriesNames{i}{1} countryAbbr]});
     delta = db_q{[seriesNames{i}{1} countryAbbr]}-dc_q{[seriesNames{i}{1} countryAbbr]};
     delta = delta.tex_rename('$\Delta$');
-    rep = rep.addSeries('data', delta, ...
-                        'tableShowMarkers', true, ...
-                        'tableAlignRight', true);
+    rep.addSeries('data', delta, ...
+        'tableShowMarkers', true, ...
+        'tableAlignRight', true);
 end
 end
diff --git a/test/createReport.m b/test/createReport.m
index 6efcb6d5c5e8fc81f233c484dcab5f1dd5253c88..33b4f41b8bd84f915e5f0854945537da338df5f9 100644
--- a/test/createReport.m
+++ b/test/createReport.m
@@ -1,5 +1,7 @@
 function createReport(dc_a, dc_q, db_a, db_q)
-% Copyright (C) 2013-2017 Dynare Team
+%function createReport(dc_a, dc_q, db_a, db_q)
+%
+% Copyright (C) 2013-2019 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -36,95 +38,95 @@ rep = report();
 
 
 %% Page 1: GDP
-rep = rep.addPage('title', 'Jan1 vs Jan2', ...
-                  'titleFormat', '\large\bfseries');
-rep = rep.addSection();
-rep = rep.addVspace();
+rep.addPage('title', 'Jan1 vs Jan2', ...
+    'titleFormat', '\large\bfseries');
+rep.addSection();
+rep.addVspace();
 
 % Table 1
-rep = rep.addTable('title', {'Real GDP Growth','subtitle 1', 'subtitle 2'}, ...
-                   'range', larange, ...
-                   'vlineAfter', dates('2011y'), ...
-                   'highlightRows', {'gray!25','white','green!22'});
+rep.addTable('title', {'Real GDP Growth','subtitle 1', 'subtitle 2'}, ...
+    'range', larange, ...
+    'vlineAfter', dates('2011y'), ...
+    'highlightRows', {'gray!25','white','green!22'});
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_GROWTH4_', larange);
-rep = rep.addVspace('number', 2);
+rep.addVspace('number', 2);
 
 % Table 2
-rep = rep.addTable('title', 'Potential GDP Growth', 'range', larange, ...
+rep.addTable('title', 'Potential GDP Growth', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_GROWTH4_BAR_', larange);
 
 
 %% Page 2: Headline & Core Inflation
-rep = rep.addPage('title', 'Jan1 vs Jan2', ...
+rep.addPage('title', 'Jan1 vs Jan2', ...
                   'titleFormat', '\large\bfseries');
-rep = rep.addSection();
-rep = rep.addVspace();
+rep.addSection();
+rep.addVspace();
 
 % Table 1
-rep = rep.addTable('title', 'Headline CPI Inflation', 'range', larange, ...
+rep.addTable('title', 'Headline CPI Inflation', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_PIE4_', larange);
-rep = rep.addVspace('number', 2);
+rep.addVspace('number', 2);
 
 % Table 2
-rep = rep.addTable('title', 'Core CPI Inflation', 'range', larange, ...
+rep.addTable('title', 'Core CPI Inflation', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_PIEX4_', larange);
 
 
 %% Page 3: Gas & Food Inflation
-rep = rep.addPage('title', 'Jan1 vs Jan2', ...
+rep.addPage('title', 'Jan1 vs Jan2', ...
                   'titleFormat', '\large\bfseries');
-rep = rep.addSection();
-rep = rep.addVspace();
+rep.addSection();
+rep.addVspace();
 
 % Table 1
-rep = rep.addTable('title', 'Gas Inflation', 'range', larange, ...
+rep.addTable('title', 'Gas Inflation', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_PIE4_GAS_', larange);
-rep = rep.addVspace('number', 2);
+rep.addVspace('number', 2);
 
 % Table 2
-rep = rep.addTable('title', 'Food Inflation', 'range', larange, ...
+rep.addTable('title', 'Food Inflation', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'PCH_PIE4_CONSFOOD_', larange);
 
 
 %% Page 4: i & Output Gap
-rep = rep.addPage('title', 'Jan1 vs Jan2', ...
+rep.addPage('title', 'Jan1 vs Jan2', ...
                   'titleFormat', '\large\bfseries');
-rep = rep.addSection();
-rep = rep.addVspace();
+rep.addSection();
+rep.addVspace();
 
 % Table 1
-rep = rep.addTable('title', 'Nominal Interest Rate', 'range', larange, ...
+rep.addTable('title', 'Nominal Interest Rate', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 rep = AnnualTable(rep, db_a, dc_a, 'RS_', larange);
-rep = rep.addVspace('number', 2);
+rep.addVspace('number', 2);
 
 % Table 2
-rep = rep.addTable('title', 'Output Gap', 'range', larange, ...
+rep.addTable('title', 'Output Gap', 'range', larange, ...
                    'vlineAfter', dates('2011y'));
 db_a = db_a.tex_rename('Y_WORLD', 'World');
-rep = rep.addSeries('data', db_a{'Y_WORLD'});
+rep.addSeries('data', db_a{'Y_WORLD'});
 delta = db_a{'Y_WORLD'}-dc_a{'Y_WORLD'};
 delta = delta.tex_rename('$\Delta$');
-rep = rep.addSeries('data', delta, ...
+rep.addSeries('data', delta, ...
                     'tableShowMarkers', true, ...
                     'tableAlignRight', true);
 rep = AnnualTable(rep, db_a, dc_a, 'Y_', larange);
 
 %% Country Pages
 for i=1:length(shortNames)
-    rep = rep.addPage('title', {'Jan1 vs Jan2', longNames{i}}, ...
+    rep.addPage('title', {'Jan1 vs Jan2', longNames{i}}, ...
                       'titleFormat', {'\large\bfseries', '\large'});
-    rep = rep.addSection('cols', 5);
+    rep.addSection('cols', 5);
     rep = CountryGraphPage(rep, shortNames{i}, db_q, dc_q, prange, srange);
 
-    rep = rep.addPage('title', 'Jan1 vs Jan2', ...
+    rep.addPage('title', 'Jan1 vs Jan2', ...
                       'titleFormat', '\large\bfseries');
-    rep = rep.addSection();
+    rep.addSection();
     rep = CountryTablePage(rep, shortNames{i}, longNames{i}, db_q, dc_q, ...
                            db_a, dc_a, trange, dates('2012q2'));
 end
@@ -132,50 +134,50 @@ end
 %% Residual Reports
 % Countries
 for i=1:length(shortNames)
-    rep = rep.addPage('title', 'Residual Report Jan1 vs Jan2', ...
+    rep.addPage('title', 'Residual Report Jan1 vs Jan2', ...
                       'titleFormat', '\large\bfseries');
-    rep = rep.addSection();
+    rep.addSection();
     rep = ResidTablePage(rep, shortNames{i}, longNames{i}, db_q, dc_q, trange, dates('2012q2'));
 end
 
 % Commodities
-rep = rep.addPage('title', 'Residual Report Jan1 vs Jan2', ...
+rep.addPage('title', 'Residual Report Jan1 vs Jan2', ...
                   'titleFormat', '\large\bfseries');
-rep = rep.addSection();
+rep.addSection();
 rep = CommResidTablePage(rep, db_q, dc_q, trange, dates('2012q2'));
 
 %% Commodities Graphs
 %Page 24
-rep = rep.addPage('title', 'Jan1 vs Jan2', ...
+rep.addPage('title', 'Jan1 vs Jan2', ...
                   'titleFormat', '\large\bfseries');
-rep = rep.addSection();
+rep.addSection();
 
-rep = rep.addGraph('title', {'World Real Oil Price Index','SUBTITLE'}, ...
+rep.addGraph('title', {'World Real Oil Price Index','SUBTITLE'}, ...
                    'xrange', prange, ...
                    'shade', srange, ...
                    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
                    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
                    'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{'LRPFOOD_BAR_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPFOOD_BAR_WORLD'}, ...
                     'graphBar', true, ...
                     'graphBarColor', 'red', ...
                     'graphBarFillColor', 'gray', ...
                     'graphBarWidth', 1);
 db_q = db_q.tex_rename('LRPOIL_WORLD', 'Oil Price');
-rep = rep.addSeries('data', db_q{'LRPOIL_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPOIL_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5, ...
                     'graphMarker', 'triangle*', ...
                     'graphMarkerEdgeColor','black', ...
                     'graphMarkerSize',4);
 db_q = db_q.tex_rename('LRPOIL_BAR_WORLD', 'Equilibrium Oil Price');
-rep = rep.addSeries('data', db_q{'LRPOIL_BAR_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPOIL_BAR_WORLD'}, ...
                     'graphLineColor', 'green', ...
                     'graphLineStyle', 'solid', ...
                     'graphLineWidth', 1.5);
 
 
-rep = rep.addGraph('title', 'World Real Food Price Index', ...
+rep.addGraph('title', 'World Real Food Price Index', ...
                    'xrange', prange, ...
                    'shade', srange, ...
                    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
@@ -183,112 +185,112 @@ rep = rep.addGraph('title', 'World Real Food Price Index', ...
                    'xTickLabelRotation', 0, ...
                    'showLegend', true, ...
                    'legendAt', [.5,.5]);
-rep = rep.addSeries('data', db_q{'LRPFOOD_BAR_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPFOOD_BAR_WORLD'}, ...
                     'graphBar', true, ...
                     'graphBarColor', 'green', ...
                     'graphBarFillColor', 'yellow', ...
                     'graphBarWidth', 1);
 db_q = db_q.tex_rename('LRPFOOD_WORLD', 'Food Price');
-rep = rep.addSeries('data', db_q{'LRPFOOD_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPFOOD_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5);
 db_q = db_q.tex_rename('LRPFOOD_BAR_WORLD', 'Equilibrium Food Price');
-rep = rep.addSeries('graphVline', dates('2009q2'), ...
+rep.addSeries('graphVline', dates('2009q2'), ...
                     'graphLineColor', 'red', ...
                     'graphLineWidth', 1.5);
 
 % Page 25
-rep = rep.addPage('title', {'Jan1 vs Jan2', 'World Oil and Food Prices'}, ...
+rep.addPage('title', {'Jan1 vs Jan2', 'World Oil and Food Prices'}, ...
                   'titleFormat', {'\large\bfseries', '\large'});
-rep = rep.addSection('cols', 1);
-rep = rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', ...
+rep.addSection('cols', 1);
+rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', ...
                        'cols', 2, ...
                        'heading', '\textbf{My First Paragraph Has Two Columns}');
 
-rep = rep.addSection('cols', 1);
-rep = rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\newline', ...
+rep.addSection('cols', 1);
+rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\newline', ...
                        'heading', '\textbf{My Next Paragraphs Only Have One}', ...
                        'indent', false);
-rep = rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\newline');
+rep.addParagraph('text', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\newline');
 
-rep = rep.addSection('cols', 2);
+rep.addSection('cols', 2);
 
-rep = rep.addGraph('title', 'World Real Oil Price', ...
+rep.addGraph('title', 'World Real Oil Price', ...
                    'xrange', prange, ...
                    'shade', srange, ...
                    'xTicks', [1,5,10,15,find(srange(1)==prange),length(prange)], ...
                    'xTickLabels',{startpoint{:},'2008Q1','2009Q2','2010Q3',shaded{:}, endpoint{:}},...
                    'xTickLabelRotation', 0);
-rep = rep.addSeries('data', db_q{'LRPOIL_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPOIL_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{'LRPOIL_WORLD'}, ...
+rep.addSeries('data', dc_q{'LRPOIL_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5);
 
 srange1 = prange(1):forecast_date;
-rep = rep.addGraph('title', 'Equilibrium World Real Oil Price', ...
+rep.addGraph('title', 'Equilibrium World Real Oil Price', ...
                    'xrange', prange, ...
                    'shade', srange1);
-rep = rep.addSeries('data', db_q{'LRPOIL_BAR_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPOIL_BAR_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{'LRPOIL_BAR_WORLD'}, ...
+rep.addSeries('data', dc_q{'LRPOIL_BAR_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5);
 
-rep = rep.addGraph('title', 'World Real Food Price', ...
+rep.addGraph('title', 'World Real Food Price', ...
                    'xrange', prange, ...
                    'shade', srange, ...
                    'xTickLabels','ALL',...
                    'xTickLabelRotation', 45,...
                    'xAxisTight',false,...
                    'yAxisTight',true);
-rep = rep.addSeries('data', db_q{'LRPFOOD_WORLD'}, ...
+rep.addSeries('data', db_q{'LRPFOOD_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5);
-rep = rep.addSeries('data', dc_q{'LRPFOOD_WORLD'}, ...
+rep.addSeries('data', dc_q{'LRPFOOD_WORLD'}, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5);
-rep = rep.addSeries('graphHline', 460, ...
+rep.addSeries('graphHline', 460, ...
                     'graphLineColor', 'red', ...
                     'graphLineWidth', 1.5);
 
 a=dseries([1:200]', '1984q1');
-b=copy(a);
-c=copy(a);
-d=copy(a);
+b=dseries([1:200]', '1984q1');
+c=dseries([1:200]', '1984q1');
+d=dseries([1:200]', '1984q1');
 b(dates('2012q2'):dates('2015q2'))=b(dates('2012q2'):dates('2015q2'))+2;
 c(dates('2012q2'):dates('2015q2'))=c(dates('2012q2'):dates('2015q2'))+4;
 d(dates('2012q2'):dates('2015q2'))=d(dates('2012q2'):dates('2015q2'))+6;
 
-rep = rep.addGraph('title', 'Equilibrium World Real Food Price', ...
+rep.addGraph('title', 'Equilibrium World Real Food Price', ...
                    'xrange', prange, ...
                    'shade', srange, ...
                    'showLegend', true, ...
                    'xTickLabelRotation', 0);
-rep = rep.addSeries('data', a, ...
+rep.addSeries('data', a, ...
                     'graphLineColor', 'blue', ...
                     'graphLineWidth', 1.5, ...
                     'graphLegendName', 'baseline', ...
                     'graphMiscTikzAddPlotOptions', 'mark=halfcircle*,color=red');
-rep = rep.addSeries('data', b, ...
+rep.addSeries('data', b, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5, ...
                     'graphLegendName', 'control', ...
                     'graphMiscTikzAddPlotOptions', 'mark=halfcircle*,mark options={rotate=90,scale=3}', ...
                     'graphFanShadeColor', 'red', 'graphFanShadeOpacity', 40);
-rep = rep.addSeries('data', c, ...
+rep.addSeries('data', c, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5, ...
                     'graphLegendName', 'control', ...
                     'graphFanShadeColor', 'red', 'graphFanShadeOpacity', 30);
-rep = rep.addSeries('data', d, ...
+rep.addSeries('data', d, ...
                     'graphLineColor', 'blue', ...
                     'graphLineStyle', 'dashed', ...
                     'graphLineWidth', 1.5, ...
diff --git a/test/runtest.m b/test/runtest.m
index 53d51cad4d351239e6aca9302effa5542efc761d..0e8b525077697569caf7332b1c5862384ceead1e 100644
--- a/test/runtest.m
+++ b/test/runtest.m
@@ -15,11 +15,8 @@
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
-addpath('../dynare/matlab/utilities/general')
-addpath('../dseries/src')
-addpath('../src')
-
-initialize_dseries_class;
+initialize_dseries_class();
+initialize_reporting_toolbox();
 
 db_a = dseries('db_a.csv');
 db_q = dseries('db_q.csv');