50
76
if ((ch >= 'a' && ch <= 'z') || (ch>= 'A' && ch <= 'Z' )) {
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."));
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 int 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 (context.get_variable (key)));
202
err_print_ln ("Something went wrong: (%: %)", e.domain, e.message);
203
assert_not_reached ();
208
protected void set_error (Error e) {
211
result_string = "Error";
213
set_variable_cach_values ();
218
protected void set_result (Token root_token) {
220
evaluated_once = true;
222
result_value = root_token.result_value;
223
result_max_value = root_token.result_max_value;
224
result_min_value = root_token.result_min_value;
225
result_string = root_token.result_string;
227
set_variable_cach_values ();
232
protected void evaluate () throws Error {
236
if (root_token == null) {
237
root_token = new RootToken (root);
240
root_token.evaluate (context);
242
set_result (root_token);
250
* Add a note (operator) to the stack after popping it's parameters.
251
* @param operand_stack stack
252
* @param operator operator.
254
protected void add_node (Stack<Token> operand_stack, Token operator) throws Error {
255
if (operator is FunctionToken) {
256
FunctionToken funk = (FunctionToken) operator;
257
int param_num = funk.next_child_num;
258
for (var i = 0; i < param_num; i++) {
259
Token param_child = operand_stack.pop ();
260
funk.set_child (param_num - 1, param_child);
262
operand_stack.push (funk);
264
} else if (operator is UnaryOperator && ((UnaryOperator) operator).is_unary) {
265
if (operand_stack.elements < 1) {
266
throw new OperandError.MISSING_OPERAND (@"Missing operand. Position: $(operator.position)");
269
if (operand_stack.elements < 2) {
270
throw new OperandError.MISSING_OPERAND (@"Missing operand. Position: $(operator.position)");
272
operator.set_right_child (operand_stack.pop ());
273
operator.set_left_child (operand_stack.pop ());
274
operand_stack.push (operator);
277
} // end of Parser class