-
Notifications
You must be signed in to change notification settings - Fork 26
/
parsetype.hpp
179 lines (144 loc) · 4.59 KB
/
parsetype.hpp
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#ifndef PARSETYPE_HPP
#define PARSETYPE_HPP
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <memory>
#include <boost/variant.hpp>
#include <gmpxx.h>
#include "bigint.hpp"
struct parse_t;
typedef std::string val_t;
typedef std::vector<parse_t> args_t;
typedef parse_t command;
typedef parse_t expr;
typedef parse_t test;
namespace checktestdata {
struct none_t {};
std::ostream& operator<<(std::ostream&, const none_t&);
struct value_t {
boost::variant<none_t, bigint, mpf_class, std::string> val;
value_t(): val(none_t()) {}
explicit value_t(bigint x): val(x) {}
explicit value_t(mpf_class x): val(x) {}
explicit value_t(std::string x): val(x) {}
operator bigint() const;
operator mpf_class() const;
// This is a member function instead of a casting operator, since
// otherwise the string could be used in other implicit casts.
std::string getstr() const;
// This converts any value type to a string representation.
std::string tostr() const;
};
const int value_none = 0;
const int value_int = 1;
const int value_float = 2;
const int value_string = 3;
} // namespace checktestdata
std::ostream &operator<<(std::ostream &, const parse_t &);
struct parse_t {
val_t val;
args_t args;
char op;
/*
Operator/type of this node, can be any of the following:
+-*%/^ standard binary arithmetic operations
n (unary) negation
? a comparison operator stored in 'val'
|&! logical AND,OR,NOT
EMUA EOF,MATCH,UNIQUE,INARRAY keywords used within test expressions
I integer constant
F float constant
S string constant
a variable assigment with two arguments: variable name, expression.
f function returning a value
l list of expressions (e.g. for array indices or argument list)
v variable with array indices in second argument
@ command with list of arguments provided in second argument,
' ' command
~ uninitialized object, to detect unset default arguments
*/
mutable long cached_long = LONG_MIN;
mutable checktestdata::value_t cache;
parse_t(): val(), args(), op('~') {}
parse_t(args_t _args): val(), args(_args), op(' ') {}
parse_t(val_t _val, args_t _args): val(_val), args(_args), op(' ') {}
// Parsing command with optional arguments
explicit
parse_t(val_t _val, parse_t arg1 = parse_t(),
parse_t arg2 = parse_t(),
parse_t arg3 = parse_t(),
parse_t arg4 = parse_t(),
parse_t arg5 = parse_t(),
parse_t arg6 = parse_t())
: val(_val), args(), op(' ')
{
if ( arg1.op!='~' ) args.push_back(arg1);
if ( arg2.op!='~' ) args.push_back(arg2);
if ( arg3.op!='~' ) args.push_back(arg3);
if ( arg4.op!='~' ) args.push_back(arg4);
if ( arg5.op!='~' ) args.push_back(arg5);
if ( arg6.op!='~' ) args.push_back(arg6);
}
// Parsing arithmetic/logical/compare operator and some other
// special cases
explicit
parse_t(char _op, parse_t arg1 = parse_t(),
parse_t arg2 = parse_t(),
parse_t arg3 = parse_t(),
parse_t arg4 = parse_t(),
parse_t arg5 = parse_t(),
parse_t arg6 = parse_t())
: val(), args(), op(_op)
{
switch ( op ) {
case 'l': // list: create new or append one argument
if ( arg2.op=='~' ) {
if ( arg1.op!='~' ) args.push_back(arg1);
} else {
args = arg1.args;
args.push_back(arg2);
}
break;
case 'I': // integer, float, string literal values
case 'F':
case 'S':
val = arg1.val;
break;
case 'a': // variable assignment
args.push_back(arg1);
args.push_back(arg2);
break;
case 'v': // variable, read index from arg2 if present
val = arg1.val;
if ( arg2.op=='l' ) args = arg2.args;
break;
case '@': // Command with argument list in arg2
op = ' ';
val = arg1.val;
args = arg2.args;
break;
case 'U': // UNIQUE test, has argument list in arg1
args = arg1.args;
break;
case '?': // comparison operator as arg1
val = arg1.val;
args.push_back(arg2);
args.push_back(arg3);
break;
default:
if ( arg1.op!='~' ) args.push_back(arg1);
if ( arg2.op!='~' ) args.push_back(arg2);
if ( arg3.op!='~' ) args.push_back(arg3);
if ( arg4.op!='~' ) args.push_back(arg4);
if ( arg5.op!='~' ) args.push_back(arg5);
if ( arg6.op!='~' ) args.push_back(arg6);
}
}
const val_t& name() const { return val; }
size_t nargs() const { return args.size(); }
const char* c_str() const { return val.c_str(); }
operator const std::string& () const { return val; }
};
#endif /* PARSETYPE_HPP */