summaryrefslogtreecommitdiffstats
path: root/src/model_parser.hpp
blob: c15a50e80b8f195e47d45950ec504f9ba57b1cdd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDED_IXION_MODEL_PARSER_HPP
#define INCLUDED_IXION_MODEL_PARSER_HPP

#include "ixion/exceptions.hpp"
#include "ixion/model_context.hpp"
#include "ixion/formula_result.hpp"

#include "session_handler.hpp"
#include "table_handler.hpp"

#include <string>
#include <exception>
#include <vector>
#include <unordered_map>

namespace ixion {

class model_parser
{
    enum parse_mode_type
    {
        parse_mode_unknown = 0,
        parse_mode_init,
        parse_mode_result,
        parse_mode_result_cache,
        parse_mode_edit,
        parse_mode_table,
        parse_mode_session,
        parse_mode_named_expression,
        parse_mode_exit
    };

    using parsed_assignment_type = std::pair<std::string_view, std::string_view>;

    struct named_expression_type
    {
        std::string name;
        std::string expression;
        abs_address_t origin;
        sheet_t scope = global_scope;
    };

    /**
     * Right-hand-side cell content type.
     */
    enum cell_type
    {
        ct_unknown = 0,
        ct_formula,
        ct_value,
        ct_string,
        ct_boolean
    };

    struct cell_def_type
    {
        std::string_view name;
        std::string_view value;
        cell_type type;
        abs_range_t pos;

        bool matrix_value = false;
    };

public:
    typedef std::unordered_map< ::std::string, formula_result> results_type;

    class parse_error : public general_error
    {
    public:
        explicit parse_error(const std::string& msg);
    };

    class check_error : public general_error
    {
    public:
        check_error(const ::std::string& msg);
    };

    model_parser() = delete;
    model_parser(const model_parser&) = delete;
    model_parser& operator= (model_parser) = delete;

    model_parser(const ::std::string& filepath, size_t thread_count);
    ~model_parser();

    void parse();

private:
    void init_model();

    void parse_command();

    void parse_session();
    void parse_init();
    void parse_edit();
    void parse_result();
    void parse_result_cache();

    void parse_table();
    void parse_table_columns(std::string_view str);
    void push_table();

    void parse_named_expression();
    void push_named_expression();

    void print_dependency();

    /**
     * Parse a simple left=right assignment line.
     */
    parsed_assignment_type parse_assignment();

    cell_def_type parse_cell_definition();

    void check();

    std::string get_display_cell_string(const abs_address_t& pos) const;
    std::string get_display_range_string(const abs_range_t& pos) const;

private:

    model_context m_context;
    table_handler m_table_handler;
    session_handler::factory m_session_handler_factory;
    std::unique_ptr<table_handler::entry> mp_table_entry;
    std::unique_ptr<formula_name_resolver> mp_name_resolver;
    std::unique_ptr<named_expression_type> mp_named_expression;
    std::string m_filepath;
    std::string m_strm;
    size_t m_thread_count;
    abs_range_set_t m_dirty_formula_cells;
    abs_range_set_t m_modified_cells;
    results_type m_formula_results;

    const char* mp_head;
    const char* mp_end;
    const char* mp_char;

    sheet_t m_current_sheet;

    parse_mode_type m_parse_mode;
    bool m_print_separator:1;
    bool m_print_sheet_name:1;
};

}

#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */