76
50
if ((ch >= 'a' && ch <= 'z') || (ch>= 'A' && ch <= 'Z' )) {
85
private static string[] EMPTY_VAR_KEYS = new string[0];
86
private Context context = null;
87
/** Contains the used variable names. */
88
private string[] variable_keys;
89
/** contains the used variables and their last value. */
90
private HashTable<string, Variable?> variable_cache;
91
/** Will contain the Root of the token tree.
92
* Asumes that there it has no parents.*/
93
private Token root_token;
95
private bool parsed = false;
96
private bool evaluated_once;
97
private string internal_experisson;
98
public string expression {
99
get {return internal_experisson;}
100
set {internal_experisson = value;
101
expression_size = value.length;
104
private size_t expression_size = 0;
105
private char cur_char = 0;
106
private int32 index = -1;
108
private FastNumber result_value;
109
private FastNumber result_max_value;
110
private FastNumber result_min_value;
112
private string result_string;
113
private Error? error;
116
public Parser (string expression) {
117
this.expression = expression;
118
this.expression_size = expression.length;
119
this.cur_char = expression[0];
123
public Parser.empty () {
127
public void reset () {
131
evaluated_once = false;
132
result_value = FastNumber (0);
133
result_min_value = FastNumber (0);
134
result_max_value = FastNumber (0);
136
variable_cache.remove_all ();
137
variable_keys = EMPTY_VAR_KEYS;
143
* Parse the expersson string.
145
public void parse () throws ParseError {
147
throw new ParseError.ALLREADY_PARSED
148
("Data has allparsed been parsed.");
152
while (this.index <= this.expression_size) {
153
switch (CharType.from_char (this.cur_char)) {
155
this.parse_advance ();
158
assert_not_reached ();
165
* advance the parser.
167
private void parse_advance () {
168
if (this.index < this.expression_size && this.cur_char != '\0') {
170
this.cur_char = this.expression[this.index];
174
protected bool valid_bounds () {
175
if (!evaluated_once) {
179
if (context != null) {
181
foreach (var key in variable_keys) {
182
if (!context.has_name (key) ||
183
!variable_cache.get (key).equals (context.get_variable (key))) {
188
err_print_ln ("Something went wrong: (%: %)", e.domain, e.message);
189
assert_not_reached ();
195
protected void set_variable_cach_values () {
196
if (context != null) {
198
foreach (var key in variable_keys) {
199
variable_cache.insert (key, Variable.copy
200
(context.get_variable (key)));
203
err_print_ln ("Something went wrong: (%: %)", e.domain, e.message);
204
assert_not_reached ();
209
protected void set_error (Error e) {
212
result_string = "Error";
214
set_variable_cach_values ();
219
protected void set_result (Token root_token) {
221
evaluated_once = true;
223
result_value = root_token.result_value;
224
result_max_value = root_token.result_max_value;
225
result_min_value = root_token.result_min_value;
226
result_string = root_token.result_string;
228
set_variable_cach_values ();
233
protected void evaluate () throws Error {
237
if (root_token == null) {
238
root_token = new RootToken (root);
241
root_token.evaluate (context);
243
set_result (root_token);
251
* Add a note (operator) to the stack after popping it's parameters.
252
* @param operand_stack stack
253
* @param operator operator.
255
protected void add_node (Stack<Token> operand_stack,
256
Token operator) throws Error {
257
if (operator is FunctionToken) {
258
FunctionToken funk = (FunctionToken) operator;
259
int32 param_num = funk.next_child_num;
260
for (var i = 0; i < param_num; i++) {
261
Token param_child = operand_stack.pop ();
262
funk.set_child (param_num - 1, param_child);
264
operand_stack.push (funk);
266
} else if (operator is UnaryOperator &&
267
((UnaryOperator) operator).is_unary) {
268
if (operand_stack.elements < 1) {
269
throw new OperandError.MISSING_OPERAND
270
(@"Missing operand. Position: $(operator.position)");
273
if (operand_stack.elements < 2) {
274
throw new OperandError.MISSING_OPERAND
275
(@"Missing operand. Position: $(operator.position)");
277
operator.set_right_child (operand_stack.pop ());
278
operator.set_left_child (operand_stack.pop ());
279
operand_stack.push (operator);
282
} // end of Parser class
53
assert_not_reached ();
58
public string parser_error_to_string (ParserError e) {
60
case (ParserError.NOT_READY):
62
case (ParserError.INVALID_DATA):
63
return "INVALID_DATA";
65
assert_not_reached ();
71
private bool ready = false;
72
private string? data = null;
73
private size_t data_size = 0;
74
private Array<Token> tokens = null;
75
private char cur_char = 0;
76
private int index = -1;
78
public Lexer (string data) {
79
assert (data.length != 0);
81
this.data_size = data.length;
82
this.cur_char = data[0];
84
tokens = new Array<Token> ();
88
public void lex () throws ParserError {
89
while (this.index <= this.data_size) {
95
private void advance () {
96
if (this.index < this.data_size && this.cur_char != '\0') {
98
this.cur_char = this.data[this.index];
100
assert_not_reached ();
105
public Array<Token>? get_tokens () throws ParserError {
107
throw (new ParserError.NOT_READY ("Lexer is not ready." +
108
"Needs to run Lexer.lex() first."));