cliparser.h 13 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/**
 * command line parser
 * @author Tobias Weber <tweber@ill.fr>
 * @date 28-may-18
 * @license see 'LICENSE' file
 */

#ifndef __CLI_PARSER_H__
#define __CLI_PARSER_H__

Tobias WEBER's avatar
Tobias WEBER committed
11
#include <sstream>
12
13
#include <string>
#include <vector>
Tobias WEBER's avatar
Tobias WEBER committed
14
#include <map>
15
#include <memory>
Tobias WEBER's avatar
Tobias WEBER committed
16

Tobias WEBER's avatar
Tobias WEBER committed
17
#include <boost/signals2/signal.hpp>
18
19
20
21
22
23

#undef yyFlexLexer
#include <FlexLexer.h>
#include "cliparser_types.h"
#include "cliparser_impl.h"

Tobias WEBER's avatar
Tobias WEBER committed
24
#include "../data.h"
25
26
27
28


class CliAST;
class CliParserContext;
Tobias WEBER's avatar
Tobias WEBER committed
29
class Symbol;
30

31
32
33
34
35
36
37
38


// ----------------------------------------------------------------------------
// Lexer
// ----------------------------------------------------------------------------

class CliLexer : public yyFlexLexer
{
Tobias WEBER's avatar
Tobias WEBER committed
39
40
41
42
43
44
private:
	CliParserContext *m_pContext = nullptr;

protected:
	virtual void LexerError(const char *err) override;

45
public:
Tobias WEBER's avatar
Tobias WEBER committed
46
	CliLexer(CliParserContext *ctx = nullptr);
47
48
49
	virtual yy::CliParser::symbol_type yylex(CliParserContext &context);
};

Tobias WEBER's avatar
Tobias WEBER committed
50
template<class t_real_cli> t_real_cli str_to_real(const std::string& str);
51
52
53
54
55

// ----------------------------------------------------------------------------



56

57
58
59
60
61
62
63
64
// ----------------------------------------------------------------------------
// Parser
// ----------------------------------------------------------------------------

class CliParserContext
{
private:
	CliLexer m_lex;
65
	std::vector<std::shared_ptr<CliAST>> m_asts;
Tobias WEBER's avatar
Tobias WEBER committed
66
67
	std::vector<std::string> m_errors;

Tobias WEBER's avatar
Tobias WEBER committed
68
69
70
71
	// symbol tables and update signal
	std::map<std::string, std::shared_ptr<Symbol>> *m_workspace = nullptr;
	boost::signals2::signal<void(const std::string&)> m_WorkspaceUpdated;

72
73
public:
	CliLexer& GetLexer() { return m_lex; }
Tobias WEBER's avatar
Tobias WEBER committed
74

Tobias WEBER's avatar
Tobias WEBER committed
75
76
77
78
79
80
81
82
83
	void PrintErrorString(const std::string &err);

	template<typename ...T> void PrintError(T&&... msgs)
	{
		std::ostringstream ostr;
		(ostr << ... << std::forward<T>(msgs));
		PrintErrorString(ostr.str());
	}

Tobias WEBER's avatar
Tobias WEBER committed
84
85
86
87
	const std::vector<std::string>& GetErrors() const { return m_errors; }
	void ClearErrors() { m_errors.clear(); }

	void SetLexerInput(std::istream &istr);
88
89
90
91

	void AddAST(std::shared_ptr<CliAST> ast) { m_asts.push_back(ast); }
	void ClearASTs() { m_asts.clear(); }
	const std::vector<std::shared_ptr<CliAST>>& GetASTs() const { return m_asts; }
Tobias WEBER's avatar
Tobias WEBER committed
92
93
94
95
96
97

	void SetWorkspace(std::map<std::string, std::shared_ptr<Symbol>> *ws) { m_workspace = ws; }
	std::map<std::string, std::shared_ptr<Symbol>> * GetWorkspace() { return m_workspace; }

	void EmitWorkspaceUpdated(const std::string& ident="") { m_WorkspaceUpdated(ident); }
	boost::signals2::signal<void(const std::string&)>& GetWorkspaceUpdatedSignal() { return m_WorkspaceUpdated; }
98
99
100
101
102
103
};

// ----------------------------------------------------------------------------



104
105

// ----------------------------------------------------------------------------
Tobias WEBER's avatar
Tobias WEBER committed
106
// Symbols
107
108
// ----------------------------------------------------------------------------

Tobias WEBER's avatar
Tobias WEBER committed
109
110
enum class SymbolType
{
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
111
112
113
114
	REAL,	// e.g. 12.3
	STRING,	// e.g. "abc"
	LIST,	// e.g. 1, 2, 3
	ARRAY,	// e.g. [1, 2, 3]
115
	MAP,	// e.g. {"key" : 1.23}
Tobias WEBER's avatar
Tobias WEBER committed
116
117
118
119
	DATASET
};


120
121
122
123
124
class Symbol
{
public:
	virtual ~Symbol() {}

Tobias WEBER's avatar
Tobias WEBER committed
125
	virtual SymbolType GetType() const = 0;
126
	virtual std::shared_ptr<Symbol> copy() const = 0;
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
127
	virtual void print(std::ostream& ostr) const = 0;
Tobias WEBER's avatar
Tobias WEBER committed
128

Tobias WEBER's avatar
Tobias WEBER committed
129
130
131
	virtual std::string serialise() const = 0;
	static std::shared_ptr<Symbol> unserialise(const std::string &str);

Tobias WEBER's avatar
Tobias WEBER committed
132
133
134
135
136
137
138
	static std::shared_ptr<Symbol> uminus(const Symbol &sym2);
	static std::shared_ptr<Symbol> add(const Symbol &sym1, const Symbol &sym2);
	static std::shared_ptr<Symbol> sub(const Symbol &sym1, const Symbol &sym2);
	static std::shared_ptr<Symbol> mul(const Symbol &sym1, const Symbol &sym2);
	static std::shared_ptr<Symbol> div(const Symbol &sym1, const Symbol &sym2);
	static std::shared_ptr<Symbol> mod(const Symbol &sym1, const Symbol &sym2);
	static std::shared_ptr<Symbol> pow(const Symbol &sym1, const Symbol &sym2);
Tobias WEBER's avatar
Tobias WEBER committed
139

Tobias WEBER's avatar
Tobias WEBER committed
140
141
142
143
144
	static std::shared_ptr<Symbol> add(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
	static std::shared_ptr<Symbol> sub(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
	static std::shared_ptr<Symbol> mul(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
	static std::shared_ptr<Symbol> div(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);

Tobias WEBER's avatar
Tobias WEBER committed
145
	static const std::string& get_type_name(const Symbol &sym);
146
147
148
149
150
151
};


class SymbolReal : public Symbol
{
private:
Tobias WEBER's avatar
Tobias WEBER committed
152
	t_real_cli m_val = 0;
153
154
155

public:
	SymbolReal() = default;
Tobias WEBER's avatar
Tobias WEBER committed
156
	SymbolReal(t_real_cli val) : m_val(val) {}
157
158
	virtual ~SymbolReal() {}

Tobias WEBER's avatar
Tobias WEBER committed
159
	virtual SymbolType GetType() const override { return SymbolType::REAL; }
Tobias WEBER's avatar
Tobias WEBER committed
160
	t_real_cli GetValue() const { return m_val; }
Tobias WEBER's avatar
Tobias WEBER committed
161
	void SetValue(t_real_cli val) { m_val = val; }
Tobias WEBER's avatar
Tobias WEBER committed
162

163
	virtual std::shared_ptr<Symbol> copy() const override { return std::make_shared<SymbolReal>(m_val); }
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
164
	virtual void print(std::ostream& ostr) const override { ostr << GetValue(); }
Tobias WEBER's avatar
Tobias WEBER committed
165
	virtual std::string serialise() const override;
166
167
168
169
170
171
172
173
174
175
176
};


class SymbolString : public Symbol
{
private:
	std::string m_val;

public:
	SymbolString() = default;
	SymbolString(const std::string& val) : m_val(val) {}
Tobias WEBER's avatar
Tobias WEBER committed
177
	SymbolString(std::string&& val) : m_val(val) {}
178
179
	virtual ~SymbolString() {}

Tobias WEBER's avatar
Tobias WEBER committed
180
181
182
	virtual SymbolType GetType() const override { return SymbolType::STRING; }
	const std::string& GetValue() const { return m_val; }

183
	virtual std::shared_ptr<Symbol> copy() const override { return std::make_shared<SymbolString>(m_val); }
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
184
	virtual void print(std::ostream& ostr) const override { ostr << GetValue(); }
Tobias WEBER's avatar
Tobias WEBER committed
185
	virtual std::string serialise() const override;
186
187
188
};


Tobias WEBER's avatar
Tobias WEBER committed
189
190
191
192
class SymbolList : public Symbol
{
private:
	std::vector<std::shared_ptr<Symbol>> m_val;
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
193
	bool m_islist = true;	// list or array
Tobias WEBER's avatar
Tobias WEBER committed
194
195
196

public:
	SymbolList() = default;
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
197
198
	SymbolList(const std::vector<std::shared_ptr<Symbol>>& val, bool islist=1) : m_val(val), m_islist(islist) {}
	SymbolList(std::vector<std::shared_ptr<Symbol>>&& val, bool islist=1) : m_val(val), m_islist(islist) {}
Tobias WEBER's avatar
Tobias WEBER committed
199
200
201
202
203
	SymbolList(const std::initializer_list<std::shared_ptr<Symbol>>& lst, bool islist=1) : m_islist(islist)
	{
		for(auto iter = lst.begin(); iter !=lst.end(); ++iter)
			m_val.push_back(*iter);
	}
Tobias WEBER's avatar
Tobias WEBER committed
204
205
	virtual ~SymbolList() {}

Tobias WEBER's avatar
arrays    
Tobias WEBER committed
206
	virtual SymbolType GetType() const override { return m_islist ? SymbolType::LIST : SymbolType::ARRAY; }
Tobias WEBER's avatar
Tobias WEBER committed
207
208
	const std::vector<std::shared_ptr<Symbol>>& GetValue() const { return m_val; }

Tobias WEBER's avatar
arrays    
Tobias WEBER committed
209
210
211
212
213
214
215
216
217
218
219
220
221
	virtual std::shared_ptr<Symbol> copy() const override { return std::make_shared<SymbolList>(m_val, m_islist); }

	virtual void print(std::ostream& ostr) const override
	{
		if(!m_islist) ostr << "[ ";
		for(std::size_t i=0; i<GetValue().size(); ++i)
		{
			GetValue()[i]->print(ostr);
			if(i < GetValue().size()-1)
				ostr << ", ";
		}
		if(!m_islist) ostr << " ]";
	}
Tobias WEBER's avatar
Tobias WEBER committed
222
223

	virtual std::string serialise() const override;
Tobias WEBER's avatar
Tobias WEBER committed
224
225
226
};


227
228
229
230
231
232
233
234
class SymbolDataset : public Symbol
{
private:
	Dataset m_val;

public:
	SymbolDataset() = default;
	SymbolDataset(const Dataset& val) : m_val(val) {}
Tobias WEBER's avatar
Tobias WEBER committed
235
	SymbolDataset(Dataset&& val) : m_val(val) {}
236
237
	virtual ~SymbolDataset() {}

Tobias WEBER's avatar
Tobias WEBER committed
238
239
240
	virtual SymbolType GetType() const override { return SymbolType::DATASET; }
	const Dataset& GetValue() const { return m_val; }

241
	virtual std::shared_ptr<Symbol> copy() const override { return std::make_shared<SymbolDataset>(m_val); }
Tobias WEBER's avatar
arrays    
Tobias WEBER committed
242
	virtual void print(std::ostream& ostr) const override { ostr << "&lt;Dataset&gt;"; }
Tobias WEBER's avatar
Tobias WEBER committed
243
	virtual std::string serialise() const override;
244
245
};

Tobias WEBER's avatar
Tobias WEBER committed
246

247
248
249
250
251
252
253
254
255
256

/**
 * write symbol to ostream
 */
static inline std::ostream& operator<< (std::ostream& ostr, const Symbol& sym)
{
	sym.print(ostr);
	return ostr;
}

257
258
259
260
261
// ----------------------------------------------------------------------------




262
263
264
265
// ----------------------------------------------------------------------------
// AST
// ----------------------------------------------------------------------------

Tobias WEBER's avatar
Tobias WEBER committed
266
267
268
269
270
271
272
273
274
275
276
277
enum class CliASTType
{
	REAL,
	STRING,
	IDENT,
	ASSIGN,
	PLUS,
	MINUS,
	MULT,
	DIV,
	MOD,
	POW,
Tobias WEBER's avatar
Tobias WEBER committed
278
	CALL,
Tobias WEBER's avatar
Tobias WEBER committed
279
280
	EXPRLIST,
	ARRAY,
281
	ARRAYACCESS,
Tobias WEBER's avatar
Tobias WEBER committed
282
283
284
};


285
286
287
288
289
290
291
292
293
294
295
296
class CliAST
{
protected:
	std::shared_ptr<CliAST> m_left;
	std::shared_ptr<CliAST> m_right;

public:
	CliAST(std::shared_ptr<CliAST> left=nullptr, std::shared_ptr<CliAST> right=nullptr) : m_left(left), m_right(right) {}

	void SetLeft(std::shared_ptr<CliAST> left) { m_left = left; }
	void SetRight(std::shared_ptr<CliAST> right) { m_right = right; }

Tobias WEBER's avatar
Tobias WEBER committed
297
	virtual void Print(std::ostringstream &ostr, int indent = 0) const;
Tobias WEBER's avatar
Tobias WEBER committed
298
299
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const = 0;
	virtual CliASTType GetType() const = 0;
300
301
302
303
304
305
306
307
308
309
310
};


class CliASTReal : public CliAST
{
protected:
	t_real_cli m_val = t_real_cli(0);

public:
	CliASTReal(t_real_cli val) : m_val(val) { }

Tobias WEBER's avatar
Tobias WEBER committed
311
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
312
313
314
315
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::REAL; }
	t_real_cli GetValue() const { return m_val; }
316
317
318
319
320
321
322
323
324
325
326
};


class CliASTString : public CliAST
{
protected:
	std::string m_val;

public:
	CliASTString(const std::string& val) : m_val(val) { }

Tobias WEBER's avatar
Tobias WEBER committed
327
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
328
329
330
331
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::STRING; }
	const std::string& GetValue() const { return m_val; }
332
333
334
335
336
337
338
339
340
341
342
};


class CliASTIdent : public CliAST
{
protected:
	std::string m_val;

public:
	CliASTIdent(const std::string& val) : m_val(val) { }

Tobias WEBER's avatar
Tobias WEBER committed
343
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
344
345
346
347
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::IDENT; }
	const std::string& GetValue() const { return m_val; }
348
349
350
351
352
353
354
355
};


class CliASTAssign : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
356
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
357
358
359
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::ASSIGN; }
360
361
362
363
364
365
366
367
};


class CliASTPlus : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
368
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
369
370
371
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::PLUS; }
372
373
374
375
376
377
378
379
};


class CliASTMinus : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
380
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
381
382
383
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::MINUS; }
384
385
386
387
388
389
390
391
};


class CliASTMult : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
392
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
393
394
395
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::MULT; }
396
397
398
399
400
401
402
403
};


class CliASTDiv : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
404
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
405
406
407
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::DIV; }
408
409
410
411
412
413
414
415
};


class CliASTMod : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
416
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
417
418
419
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::MOD; }
420
421
422
423
424
425
426
427
};


class CliASTPow : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
428
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
429
430
431
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::POW; }
432
433
434
435
436
437
438
439
};


class CliASTCall : public CliAST
{
public:
	using CliAST::CliAST;

Tobias WEBER's avatar
Tobias WEBER committed
440
	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
Tobias WEBER's avatar
Tobias WEBER committed
441
442
443
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::CALL; }
444
445
};

Tobias WEBER's avatar
Tobias WEBER committed
446
447
448
449
450
451
452
453
454
455
456
457

class CliASTExprList : public CliAST
{
public:
	using CliAST::CliAST;

	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::EXPRLIST; }
};

Tobias WEBER's avatar
Tobias WEBER committed
458
459
460
461
462
463
464
465
466
467
468
469

class CliASTArray : public CliAST
{
public:
	using CliAST::CliAST;

	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::ARRAY; }
};

470
471
472
473
474
475
476
477
478
479
480
481
482

class CliASTArrayAccess : public CliAST
{
public:
	using CliAST::CliAST;

	virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
	virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;

	virtual CliASTType GetType() const override { return CliASTType::ARRAYACCESS; }
};


483
484
485
486
487
488
489
490
// ----------------------------------------------------------------------------



#undef YY_DECL
#define YY_DECL yy::CliParser::symbol_type CliLexer::yylex(CliParserContext &context)
extern yy::CliParser::symbol_type yylex(CliParserContext &context);

Tobias WEBER's avatar
Tobias WEBER committed
491
#define yyterminate() return yy::CliParser::token::yytokentype(YY_NULL);
492
493
494


#endif