1 /* --------------------------------------------------------------------------
2 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
3
4 CppAD is distributed under the terms of the
5 Eclipse Public License Version 2.0.
6
7 This Source Code may also be made available under the following
8 Secondary License when the conditions for such availability set forth
9 in the Eclipse Public License, Version 2.0 are satisfied:
10 GNU General Public License, Version 2.0 or later.
11 ---------------------------------------------------------------------------- */
12
13 # include <cppad/cppad.hpp>
14
json_lexer(void)15 bool json_lexer(void)
16 { bool ok = true;
17 typedef CppAD::graph::graph_op_enum graph_op_enum;
18 using CppAD::local::graph::op_name2enum;
19 //
20 // match_any_string
21 std::string match_any_string = "";
22 //
23 // An AD graph example
24 // node_1 : p[0]
25 // node_2 : x[0]
26 // node_3 : x[1]
27 // node_4 : -2.0
28 // node_5 : p[0] + x[0] + x[1]
29 // node_6 : (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])
30 // y[0] = (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])
31 // use single quote to avoid having to escape double quote
32 std::string graph =
33 "{\n"
34 " 'op_define_vec' : [ 3, [\n"
35 " { 'op_code':1, 'name':'add', 'n_arg':2 } ,\n"
36 " { 'op_code':2, 'name':'mul', 'n_arg':2 } ,\n"
37 " { 'op_code':3, 'name':'sum' } ]\n"
38 " ],\n"
39 " 'n_dynamic_ind' : 1,\n"
40 " 'n_variable_ind' : 2,\n"
41 " 'constant_vec' : [ 1, [ -2.0 ] ],\n"
42 " 'op_usage_vec' : [ 2, [\n"
43 " [ 3, 1, 3, [1, 2, 3] ] ,\n"
44 " [ 2, 5, 5 ] ] \n"
45 " ],\n"
46 " 'dependent_vec' : [ 1, [6] ]\n"
47 "}\n";
48 // Convert the single quote to double quote
49 for(size_t i = 0; i < graph.size(); ++i)
50 if( graph[i] == '\'' ) graph[i] = '"';
51 //
52 // json_lexer constructor checks for { at beginning
53 CppAD::local::graph::json_lexer json_lexer(graph);
54 // -----------------------------------------------------------------------
55 // op_define_vec
56 json_lexer.check_next_string("op_define_vec");
57 json_lexer.check_next_char(':');
58 json_lexer.check_next_char('[');
59 //
60 // n_define
61 json_lexer.next_non_neg_int();
62 size_t n_define = json_lexer.token2size_t();
63 json_lexer.check_next_char(',');
64 json_lexer.check_next_char('[');
65 CppAD::vector<graph_op_enum> op_code2enum(1);
66 for(size_t i = 0; i < n_define; ++i)
67 { json_lexer.check_next_char('{');
68 //
69 // op_code
70 json_lexer.check_next_string("op_code");
71 json_lexer.check_next_char(':');
72 json_lexer.next_non_neg_int();
73 # ifndef NDEBUG
74 size_t op_code = json_lexer.token2size_t();
75 assert( op_code == op_code2enum.size() );
76 # endif
77 json_lexer.check_next_char(',');
78 //
79 // name
80 json_lexer.check_next_string("name");
81 json_lexer.check_next_char(':');
82 json_lexer.check_next_string(match_any_string);
83 std::string name = json_lexer.token();
84 graph_op_enum op_enum = op_name2enum[name];
85 //
86 // op_code2enum
87 op_code2enum.push_back(op_enum);
88 //
89 if( op_enum != CppAD::graph::sum_graph_op )
90 { json_lexer.check_next_char(',');
91 //
92 // n_arg
93 json_lexer.check_next_string("n_arg");
94 json_lexer.check_next_char(':');
95 json_lexer.next_non_neg_int();
96 ok &= json_lexer.token2size_t() == 2;
97 }
98 //
99 json_lexer.check_next_char('}');
100 if( i + 1 == n_define )
101 json_lexer.check_next_char(']');
102 else
103 json_lexer.check_next_char(',');
104 }
105 json_lexer.check_next_char(']');
106 json_lexer.check_next_char(',');
107 // -----------------------------------------------------------------------
108 // n_dynamic_ind
109 json_lexer.check_next_string("n_dynamic_ind");
110 json_lexer.check_next_char(':');
111 json_lexer.next_non_neg_int();
112 size_t n_dynamic_ind = json_lexer.token2size_t();
113 json_lexer.check_next_char(',');
114 //
115 ok &= n_dynamic_ind == 1;
116 // -----------------------------------------------------------------------
117 // n_variable_ind
118 json_lexer.check_next_string("n_variable_ind");
119 json_lexer.check_next_char(':');
120 json_lexer.next_non_neg_int();
121 size_t n_variable_ind = json_lexer.token2size_t();
122 json_lexer.check_next_char(',');
123 //
124 ok &= n_variable_ind == 2;
125 // -----------------------------------------------------------------------
126 // constant_vec
127 json_lexer.check_next_string("constant_vec");
128 json_lexer.check_next_char(':');
129 json_lexer.check_next_char('[');
130 json_lexer.next_non_neg_int();
131 size_t n_constant = json_lexer.token2size_t();
132 CppAD::vector<double> constant_vec(n_constant);
133 json_lexer.check_next_char(',');
134 //
135 // [ first_constant, ... , last_constant ]
136 json_lexer.check_next_char('[');
137 for(size_t i = 0; i < n_constant; ++i)
138 { json_lexer.next_float();
139 constant_vec[i] = json_lexer.token2double();
140 //
141 if( i + 1 == n_constant )
142 json_lexer.check_next_char(']');
143 else
144 json_lexer.check_next_char(',');
145 }
146 //
147 json_lexer.check_next_char(']');
148 json_lexer.check_next_char(',');
149 //
150 ok &= constant_vec.size() == 1;
151 ok &= constant_vec[0] == -2.0;
152 // -----------------------------------------------------------------------
153 // op_usage_vec
154 json_lexer.check_next_string("op_usage_vec");
155 //
156 json_lexer.check_next_char(':');
157 json_lexer.check_next_char('[');
158 //
159 json_lexer.next_non_neg_int();
160 size_t n_usage = json_lexer.token2size_t();
161 CppAD::vector<graph_op_enum> operator_vec(n_usage);
162 //
163 json_lexer.check_next_char(',');
164 //
165 // [ first_operator, ... , last_operator ]
166 json_lexer.check_next_char('[');
167 for(size_t i = 0; i < n_usage; ++i)
168 { // start next operator
169 json_lexer.check_next_char('[');
170 graph_op_enum op_usage;
171 //
172 // op_code
173 json_lexer.next_non_neg_int();
174 size_t op_code = json_lexer.token2size_t();
175 //
176 // op_enum
177 op_usage = op_code2enum[op_code];
178 json_lexer.check_next_char(',');
179 //
180 size_t n_result, n_arg;
181 if( op_usage != CppAD::graph::sum_graph_op )
182 { n_result = 1;
183 n_arg = 2;
184 }
185 else
186 { // n_result
187 json_lexer.next_non_neg_int();
188 n_result = json_lexer.token2size_t();
189 json_lexer.check_next_char(',');
190 ok &= n_result == 1;
191 //
192 // n_arg
193 json_lexer.next_non_neg_int();
194 n_arg = json_lexer.token2size_t();
195 json_lexer.check_next_char(',');
196 json_lexer.check_next_char('[');
197 ok &= n_arg == 3;
198 //
199 }
200 ok &= n_result == 1;
201 CppAD::vector<size_t> arg_node(0);
202 // first_arg_node, ... , last_arg_node
203 for(size_t j = 0; j < n_arg; ++j)
204 { // next argument node
205 json_lexer.next_non_neg_int();
206 size_t argument_node = json_lexer.token2size_t();
207 arg_node.push_back( argument_node );
208 //
209 if( j + 1 == n_arg )
210 json_lexer.check_next_char(']');
211 else
212 json_lexer.check_next_char(',');
213 }
214 if( op_usage == CppAD::graph::sum_graph_op )
215 {
216 json_lexer.check_next_char(']');
217 ok &= arg_node.size() == 3;
218 ok &= arg_node[0] == 1;
219 ok &= arg_node[1] == 2;
220 ok &= arg_node[2] == 3;
221 }
222 else
223 { ok &= arg_node.size() == 2;
224 ok &= arg_node[0] == 5;
225 ok &= arg_node[1] == 5;
226 }
227 //
228 // end of this operator
229 operator_vec[i] = op_usage;
230 //
231 if( i + 1 == n_usage )
232 json_lexer.check_next_char(']');
233 else
234 json_lexer.check_next_char(',');
235
236 }
237 json_lexer.check_next_char(']');
238 //
239 json_lexer.check_next_char(',');
240 //
241 ok &= operator_vec.size() == 2;
242 //
243 graph_op_enum op_enum = operator_vec[0];
244 ok &= op_enum == CppAD::graph::sum_graph_op;
245 //
246 op_enum = operator_vec[1];
247 ok &= op_enum == CppAD::graph::mul_graph_op;
248 // -----------------------------------------------------------------------
249 // dependent_vec
250 json_lexer.check_next_string("dependent_vec");
251 json_lexer.check_next_char(':');
252 json_lexer.check_next_char('[');
253 json_lexer.next_non_neg_int();
254 size_t n_dependent = json_lexer.token2size_t();
255 CppAD::vector<size_t> dependent_vec(n_dependent);
256 //
257 json_lexer.check_next_char(',');
258 //
259 // [ first_dependent, ... , last_dependent ]
260 json_lexer.check_next_char('[');
261 for(size_t i = 0; i < n_dependent; ++i)
262 { json_lexer.next_float();
263 dependent_vec[i] = json_lexer.token2size_t();
264 //
265 if( i + 1 == n_dependent )
266 json_lexer.check_next_char(']');
267 else
268 json_lexer.check_next_char(',');
269 }
270 //
271 json_lexer.check_next_char(']');
272 //
273 ok &= dependent_vec.size() == 1;
274 ok &= dependent_vec[0] == 6;
275 // -----------------------------------------------------------------------
276 // }
277 json_lexer.check_next_char('}');
278 //
279 return ok;
280 }
281