mupp 1.1.0
Loading...
Searching...
No Matches
PProgram.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PProgram.cpp
4
5 Author: Andreas Suter
6 e-mail: andreas.suter@psi.ch
7
8 Based on Joel de Guzman example on calc7,
9 see https://github.com/boostorg/spirit
10
11 This file implements the semantic analysis (PProgram) and evaluation
12 (PProgEval) visitor classes for the variable expression AST.
13
14 PProgram performs semantic checks:
15 - Variable declaration validation
16 - Variable reference resolution
17 - Type and operator validation
18 - Building the symbol table
19
20 PProgEval performs expression evaluation:
21 - Element-wise vector operations
22 - Mathematical function evaluation
23 - Variable value and error computation
24 - Result storage in variable handlers
25
26 Both classes use the visitor pattern to traverse the AST generated by
27 the parser and process each node type appropriately.
28
29***************************************************************************/
30
31/***************************************************************************
32 * Copyright (C) 2023 by Andreas Suter *
33 * andreas.suter@psi.ch *
34 * *
35 * This program is free software; you can redistribute it and/or modify *
36 * it under the terms of the GNU General Public License as published by *
37 * the Free Software Foundation; either version 2 of the License, or *
38 * (at your option) any later version. *
39 * *
40 * This program is distributed in the hope that it will be useful, *
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
43 * GNU General Public License for more details. *
44 * *
45 * You should have received a copy of the GNU General Public License *
46 * along with this program; if not, write to the *
47 * Free Software Foundation, Inc., *
48 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
49 ***************************************************************************/
50
51#include "PProgram.hpp"
52
53#include <boost/foreach.hpp>
54#include <boost/variant/apply_visitor.hpp>
55#include <boost/assert.hpp>
56#include <boost/lexical_cast.hpp>
57#include <boost/algorithm/string.hpp>
58#include <set>
59
60namespace mupp { namespace prog {
61 void PVarHandler::SetValue(double dval, unsigned idx)
62 {
63 if (idx >= fValue.size()) {
64 std::cerr << "**ERROR** SetValue: idx=" << idx << " is out-of-range." << std::endl;
65 return;
66 }
67 fValue[idx] = dval;
68 }
69
70 void PVarHandler::SetError(double dval, unsigned idx)
71 {
72 if (idx >= fError.size()) {
73 std::cerr << "**ERROR** SetError: idx=" << idx << " is out-of-range." << std::endl;
74 return;
75 }
76 fError[idx] = dval;
77 }
78
79 bool PProgram::operator()(double x)
80 {
81 return true;
82 }
83
85 {
86 // check that the variable exists
87 if (!find_var(x.lhs.name)) {
88 error_handler(0, "Undeclared variable: " + x.lhs.name);
89 return false;
90 }
91
92 if (!(*this)(x.rhs)) {
93 std::cout << "**SEM ERROR** in var assignment of var: " << x.lhs.name << std::endl;
94 std::cout << " rhs is missing or has an error." << std::endl;
95 return false;
96 }
97
98 return true;
99 }
100
102 {
103 if (!boost::apply_visitor(*this, x.first))
104 return false;
105
106 BOOST_FOREACH(ast::operation const& oper, x.rest) {
107 if (!(*this)(oper))
108 return false;
109 }
110
111 return true;
112 }
113
115 {
116 switch (x.func_id) {
117 case ast::fun_max:
118 case ast::fun_min:
119 case ast::fun_abs:
120 case ast::fun_sin:
121 case ast::fun_cos:
122 case ast::fun_tan:
123 case ast::fun_sinh:
124 case ast::fun_cosh:
125 case ast::fun_tanh:
126 case ast::fun_asin:
127 case ast::fun_acos:
128 case ast::fun_atan:
129 case ast::fun_exp:
130 case ast::fun_log:
131 case ast::fun_ln:
132 case ast::fun_sqrt:
133 break;
134 default:
135 BOOST_ASSERT(0);
136 return false;
137 }
138
139 if (!(*this)(x.arg)) {
140 std::cout << "**SEM ERROR** in function: arg is missing or has an error." << std::endl;
141 return false;
142 }
143
144 return true;
145 }
146
148 {
149 if (!boost::apply_visitor(*this, x.operand_))
150 return false;
151
152 switch (x.operator_) {
153 case ast::op_plus:
154 break;
155 case ast::op_minus:
156 break;
157 case ast::op_times:
158 break;
159 case ast::op_divide:
160 break;
161 case ast::op_positive:
162 break;
163 case ast::op_negative:
164 break;
165 default:
166 BOOST_ASSERT(0);
167 return false;
168 }
169
170 return true;
171 }
172
174 {
175 if (!(*this)(x.base)) {
176 std::cout << "**SEM ERROR** in power: base argument is missing or has an error." << std::endl;
177 return false;
178 }
179
180 if (!(*this)(x.pow)) {
181 std::cout << "**SEM ERROR** in power: power argument is missing or has an error." << std::endl;
182 return false;
183 }
184
185 return true;
186 }
187
189 {
190 return boost::apply_visitor(*this, x);
191 }
192
194 {
195 BOOST_FOREACH(ast::statement const& s, x) {
196 if (!(*this)(s))
197 return false;
198 }
199 return true;
200 }
201
203 {
204 if (!boost::apply_visitor(*this, x.operand_))
205 return false;
206
207 switch (x.operator_) {
208 case ast::op_negative:
209 break;
210 case ast::op_positive:
211 break;
212 default:
213 BOOST_ASSERT(0);
214 return false;
215 }
216
217 return true;
218 }
219
221 {
222 bool ok(false);
223 std::string var_name;
224
225 var_name = pos_to_var(x.name, ok);
226 if (!ok) {
227 error_handler(0, "Position variable out-of-range: " + x.name);
228 return false;
229 }
230
231 if (!find_var(var_name)) {
232 error_handler(0, "Undeclared variable: " + var_name);
233 return false;
234 }
235
236 return true;
237 }
238
240 {
241 if (find_var(x.lhs.name)) {
242 error_handler(0, "Duplicate variable: " + x.lhs.name);
243 return false;
244 }
245
246 if (x.rhs) { // if there's a RHS initializer
247 bool r = (*this)(*x.rhs);
248 if (r) { // don't add the variable if the RHS fails
249 add_var(x.lhs.name);
250 } else {
251 std::cout << "**SEM ERROR** rhs of var decl, name: " << x.lhs.name << ", failed" << std::endl;
252 return r;
253 }
254 } else {
255 add_var(x.lhs.name);
256 }
257
258 return true;
259 }
260
261 void PProgram::add_predef_var_values(const std::string &name,
262 std::vector<double> &val,
263 std::vector<double> &err)
264 {
265 unsigned int idx;
266 if (!find_var(name, idx)) {
267 std::cerr << "**ERROR** couldn't find pre-def variable : " << name << std::endl;
268 return;
269 }
270
271 fVariable[idx].SetValue(val);
272 fVariable[idx].SetError(err);
273 }
274
275 void PProgram::add_var(std::string const& name)
276 {
277 PVarHandler var;
278 var.SetName(name);
279 fVariable.push_back(var);
280 // add map var <-> pos
281 std::size_t n = fVarPos.size();
282 fVarPos[n] = name;
283 }
284
285 bool PProgram::find_var(std::string const &name)
286 {
287 unsigned int idx;
288 return find_var(name, idx);
289 }
290
291 bool PProgram::find_var(std::string const &name, unsigned int &idx)
292 {
293 bool result=false;
294
295 // remove leading '$' of identifier
296 std::string id("");
297 if (name[0] == '$')
298 id = name.substr(1);
299 else
300 id = name;
301
302 for (unsigned int i=0; i<fVariable.size(); i++) {
303 if (id == fVariable[i].GetName()) {
304 idx = i;
305 result = true;
306 break;
307 }
308 }
309
310 return result;
311 }
312
313 std::string PProgram::pos_to_var(std::string const &name, bool &ok)
314 {
315 std::string result("??");
316 ok = true;
317
318 // remove leading '$' if present
319 if (name[0] == '$')
320 result = name.substr(1);
321 else
322 result = name;
323
324 // check if number
325 char *p;
326 int num = strtol(result.c_str(), &p, 10);
327 if (*p == 0) {
328 if (num >= fVarPos.size())
329 ok = false;
330 else
331 result = fVarPos[num];
332 }
333
334 return result;
335 }
336
337
338 std::vector<double> PProgEval::operator()(ast::nil)
339 {
340 std::vector<double> result;
341 result.resize(fVariable[0].GetSize());
342
343 for (unsigned int i=0; i<result.size(); i++)
344 result[i] = 0.0;
345
346 BOOST_ASSERT(0);
347 return result;
348 }
349
350 std::vector<double> PProgEval::operator()(double x)
351 {
352 std::vector<double> result;
353 result.resize(fVariable[0].GetSize());
354
355 for (unsigned int i=0; i<result.size(); i++)
356 result[i] = x;
357
358 return result;
359 }
360
361 std::vector<double> PProgEval::operator()(ast::assignment const &x)
362 {
363 std::vector<double> result;
364 result.resize(fVariable[0].GetSize());
365
366 result = (*this)(x.rhs);
367
368 // keep all data under <varName> not <varName>Err.
369 // <varName>Err data go to <varName> error, whereas
370 // <varName> data go to <varName> value
371 std::string name = x.lhs.name;
372 bool errorVal(false);
373
374 // check for error variable
375 std::size_t pos = name.find("Err");
376 if (pos != std::string::npos) { // it is an error variable
377 name = name.substr(0, pos);
378 errorVal = true;
379 }
380
381 unsigned int idx = find_var(name);
382 if (errorVal)
383 fVariable[idx].SetError(result);
384 else
385 fVariable[idx].SetValue(result);
386
387 return result;
388 }
389
390 std::vector<double> PProgEval::operator()(ast::expression const &x)
391 {
392 std::vector<double> vec = boost::apply_visitor(*this, x.first);
393
394 BOOST_FOREACH(ast::operation const& oper, x.rest) {
395 vec = (*this)(oper, vec);
396 }
397 return vec;
398 }
399
400 std::vector<double> PProgEval::operator()(ast::function const &x)
401 {
402 std::vector<double> vec = (*this)(x.arg);
403
404 double dval;
405 switch(x.func_id) {
406 case ast::fun_max:
407 dval = -1.0e10;
408 for (unsigned int i=0; i<vec.size(); i++) {
409 if (vec[i] > dval)
410 dval = vec[i];
411 }
412 for (unsigned int i=0; i<vec.size(); i++)
413 vec[i] = dval;
414 break;
415 case ast::fun_min:
416 dval = 1.0e10;
417 for (unsigned int i=0; i<vec.size(); i++) {
418 if (vec[i] < dval)
419 dval = vec[i];
420 }
421 for (unsigned int i=0; i<vec.size(); i++)
422 vec[i] = dval;
423 break;
424 case ast::fun_abs:
425 for (unsigned int i=0; i<vec.size(); i++)
426 vec[i] = fabs(vec[i]);
427 break;
428 case ast::fun_sin:
429 for (unsigned int i=0; i<vec.size(); i++)
430 vec[i] = sin(vec[i]);
431 break;
432 case ast::fun_cos:
433 for (unsigned int i=0; i<vec.size(); i++)
434 vec[i] = cos(vec[i]);
435 break;
436 case ast::fun_tan:
437 for (unsigned int i=0; i<vec.size(); i++)
438 vec[i] = tan(vec[i]);
439 break;
440 case ast::fun_sinh:
441 for (unsigned int i=0; i<vec.size(); i++)
442 vec[i] = sinh(vec[i]);
443 break;
444 case ast::fun_cosh:
445 for (unsigned int i=0; i<vec.size(); i++)
446 vec[i] = cosh(vec[i]);
447 break;
448 case ast::fun_tanh:
449 for (unsigned int i=0; i<vec.size(); i++)
450 vec[i] = tanh(vec[i]);
451 break;
452 case ast::fun_asin:
453 for (unsigned int i=0; i<vec.size(); i++)
454 vec[i] = asin(vec[i]);
455 break;
456 case ast::fun_acos:
457 for (unsigned int i=0; i<vec.size(); i++)
458 vec[i] = acos(vec[i]);
459 break;
460 case ast::fun_atan:
461 for (unsigned int i=0; i<vec.size(); i++)
462 vec[i] = atan(vec[i]);
463 break;
464 case ast::fun_exp:
465 for (unsigned int i=0; i<vec.size(); i++)
466 vec[i] = exp(vec[i]);
467 break;
468 case ast::fun_log:
469 for (unsigned int i=0; i<vec.size(); i++) {
470 if (vec[i] <= 0.0) {
471 BOOST_ASSERT(0);
472 break;
473 } else {
474 vec[i] = log10(vec[i]);
475 }
476 }
477 break;
478 case ast::fun_ln:
479 for (unsigned int i=0; i<vec.size(); i++) {
480 if (vec[i] <= 0.0) {
481 BOOST_ASSERT(0);
482 break;
483 } else {
484 vec[i] = log(vec[i]);
485 }
486 }
487 break;
488 case ast::fun_sqrt:
489 for (unsigned int i=0; i<vec.size(); i++) {
490 if (vec[i] <= 0.0) {
491 BOOST_ASSERT(0);
492 break;
493 } else {
494 vec[i] = sqrt(vec[i]);
495 }
496 }
497 break;
498 default:
499 BOOST_ASSERT(0);
500 break;
501 }
502
503 return vec;
504 }
505
506 std::vector<double> PProgEval::operator()(ast::operation const &x, std::vector<double> lhs)
507 {
508 std::vector<double> rhs = boost::apply_visitor(*this, x.operand_);
509
510 // make sure both vectors have the same size
511 if (lhs.size() != rhs.size()) {
512 BOOST_ASSERT(0);
513 return lhs;
514 }
515
516 switch (x.operator_) {
517 case ast::op_plus:
518 for (unsigned int i=0; i<lhs.size(); i++)
519 lhs[i] = lhs[i] + rhs[i];
520 break;
521 case ast::op_minus:
522 for (unsigned int i=0; i<lhs.size(); i++)
523 lhs[i] = lhs[i] - rhs[i];
524 break;
525 case ast::op_times:
526 for (unsigned int i=0; i<lhs.size(); i++)
527 lhs[i] = lhs[i] * rhs[i];
528 break;
529 case ast::op_divide:
530 for (unsigned int i=0; i<lhs.size(); i++) {
531 if (rhs[i] == 0.0) {
532 BOOST_ASSERT(0);
533 return lhs;
534 } else {
535 lhs[i] = lhs[i] / rhs[i];
536 }
537 }
538 break;
539 default:
540 BOOST_ASSERT(0);
541 return lhs;
542 }
543
544 return lhs;
545 }
546
547 std::vector<double> PProgEval::operator()(ast::power const &x)
548 {
549 std::vector<double> baseV = (*this)(x.base);
550 std::vector<double> powV = (*this)(x.pow);
551
552 if (baseV.size() != powV.size()) {
553 BOOST_ASSERT(0);
554 return baseV;
555 }
556
557 std::vector<double> result;
558 result.resize(baseV.size());
559 for (unsigned int i=0; i<baseV.size(); i++)
560 result[i] = pow(baseV[i], powV[i]);
561
562 return result;
563 }
564
565 std::vector<double> PProgEval::operator()(ast::statement const &x)
566 {
567 // as35: not-yet-implemented
568 std::vector<double> result;
569 result.resize(fVariable[0].GetSize());
570
571 for (unsigned int i=0; i<result.size(); i++)
572 result[i] = 0.0;
573
574 boost::apply_visitor(*this, x);
575
576 return result;
577 }
578
579 std::vector<double> PProgEval::operator()(ast::statement_list const &x)
580 {
581 // as35: not-yet-implemented
582 std::vector<double> result;
583 result.resize(fVariable[0].GetSize());
584
585 for (unsigned int i=0; i<result.size(); i++)
586 result[i] = 0.0;
587
588 BOOST_FOREACH(ast::statement const& s, x) {
589 (*this)(s);
590 }
591
592 return result;
593 }
594
595 std::vector<double> PProgEval::operator()(ast::unary const &x)
596 {
597 std::vector<double> vec = boost::apply_visitor(*this, x.operand_);
598
599 if (x.operator_ == ast::op_negative) {
600 for (unsigned int i=0; i<vec.size(); i++) {
601 vec[i] *= -1.0;
602 }
603 }
604 return vec;
605 }
606
607 std::vector<double> PProgEval::operator()(ast::variable const &x)
608 {
609 std::string name = x.name;
610 bool errorVal(false);
611
612 // check for injected error variable
613 std::size_t pos = name.find("Err");
614 if (pos != std::string::npos) { // it is an error variable
615 name = name.substr(0, pos);
616 errorVal = true;
617 }
618
619 unsigned idx = find_var(name);
620
621 if (errorVal)
622 return fVariable[idx].GetError();
623 else
624 return fVariable[idx].GetValue();
625 }
626
628 {
629 std::vector<double> result;
630 result.resize(fVariable[0].GetSize());
631
632 // keep all data under <varName> not <varName>Err.
633 // <varName>Err data go to <varName> error, whereas
634 // <varName> data go to <varName> value
635 std::string name = x.lhs.name;
636 bool errorVal(false);
637
638 // check for error variable
639 std::size_t pos = name.find("Err");
640 if (pos != std::string::npos) { // it is an error variable
641 name = name.substr(0, pos);
642 errorVal = true;
643 }
644
645 unsigned int idx = find_var(name);
646
647 if (x.rhs) { // if there's a RHS initializer
648 result = (*this)(*x.rhs);
649 } else {
650 // injected variable content
651 if (errorVal)
652 result = fVariable[idx].GetError();
653 else
654 result = fVariable[idx].GetValue();
655 }
656
657 if (errorVal)
658 fVariable[idx].SetError(result);
659 else
660 fVariable[idx].SetValue(result);
661
662 return result;
663 }
664
665 unsigned int PProgEval::find_var(std::string const &name)
666 {
667 // remove leading '$' of identifier
668 std::string id("");
669 if (name[0] == '$')
670 id = name.substr(1);
671 else
672 id = name;
673
674 unsigned idx = 0;
675 for (unsigned int i=0; i<fVariable.size(); i++) {
676 if (id == fVariable[i].GetName()) {
677 idx = i;
678 break;
679 }
680 }
681
682 return idx;
683 }
684
685 PVarHandler PProgEval::getVar(const std::string name, bool &ok)
686 {
687 PVarHandler var = fVariable[0];
688 ok = false;
689
690 for (unsigned int i=0; i<fVariable.size(); i++) {
691 if (fVariable[i].GetName() == name) {
692 var = fVariable[i];
693 ok = true;
694 break;
695 }
696 }
697
698 return var;
699 }
700
702 {
703 std::vector<double> val, err;
704 for (unsigned int i=0; i<fVariable.size(); i++) {
705 if (!strstr(fVariable[i].GetName().c_str(), "Err")) {
706 std::cout << "+++++" << std::endl;
707 std::cout << "var Name: " << fVariable[i].GetName() << std::endl;
708 val = fVariable[i].GetValue();
709 err = fVariable[i].GetError();
710 for (unsigned int j=0; j<val.size(); j++) {
711 if (j<err.size())
712 std::cout << " " << j << ": " << val[j] << " +- " << err[j] << std::endl;
713 else
714 std::cout << " " << j << ": " << val[j] << std::endl;
715 }
716 }
717 }
718 std::cout << "+++++" << std::endl;
719 }
720}}
The PVarHandler class manages variable data during evaluation.
Definition PProgram.hpp:65
void SetName(std::string name)
Sets the variable name.
Definition PProgram.hpp:76
std::vector< double > fError
Vector of error values (one per run)
Definition PProgram.hpp:145
void SetError(std::vector< double > &dval)
Sets all error values for this variable.
Definition PProgram.hpp:95
std::vector< double > fValue
Vector of values (one per run)
Definition PProgram.hpp:144
void SetValue(std::vector< double > &dval)
Sets all values for this variable.
Definition PProgram.hpp:82
std::list< statement > statement_list
Type alias for a list of statements forming a program.
Definition PAst.hpp:268
@ op_minus
Subtraction operator (-)
Definition PAst.hpp:85
@ op_positive
Unary plus operator (+x)
Definition PAst.hpp:88
@ op_divide
Division operator (/)
Definition PAst.hpp:87
@ op_plus
Addition operator (+)
Definition PAst.hpp:84
@ op_times
Multiplication operator (*)
Definition PAst.hpp:86
@ op_negative
Unary minus operator (-x)
Definition PAst.hpp:89
boost::variant< variable_declaration, assignment > statement
Variant type representing a single statement.
Definition PAst.hpp:260
@ fun_sqrt
Square root function.
Definition PAst.hpp:115
@ fun_atan
Arctangent function.
Definition PAst.hpp:111
@ fun_acos
Arccosine function.
Definition PAst.hpp:110
@ fun_exp
Exponential function.
Definition PAst.hpp:112
@ fun_min
Minimum value function.
Definition PAst.hpp:101
@ fun_sin
Sine function.
Definition PAst.hpp:103
@ fun_cos
Cosine function.
Definition PAst.hpp:104
@ fun_cosh
Hyperbolic cosine function.
Definition PAst.hpp:107
@ fun_max
Maximum value function.
Definition PAst.hpp:100
@ fun_ln
Natural logarithm function.
Definition PAst.hpp:114
@ fun_log
Base-10 logarithm function.
Definition PAst.hpp:113
@ fun_tanh
Hyperbolic tangent function.
Definition PAst.hpp:108
@ fun_asin
Arcsine function.
Definition PAst.hpp:109
@ fun_sinh
Hyperbolic sine function.
Definition PAst.hpp:106
@ fun_tan
Tangent function.
Definition PAst.hpp:105
@ fun_abs
Absolute value function.
Definition PAst.hpp:102
Represents an assignment statement.
Definition PAst.hpp:234
variable lhs
The left-hand side variable being assigned to.
Definition PAst.hpp:235
expression rhs
The right-hand side expression to evaluate.
Definition PAst.hpp:236
Represents a complete expression with operator precedence.
Definition PAst.hpp:198
operand first
The first operand in the expression.
Definition PAst.hpp:199
std::list< operation > rest
Sequence of operations applied left-to-right.
Definition PAst.hpp:200
Represents a function call with a single argument.
Definition PAst.hpp:209
expression arg
The argument expression.
Definition PAst.hpp:211
funid func_id
The function identifier.
Definition PAst.hpp:210
Represents an empty/null AST node.
Definition PAst.hpp:123
Represents a binary operation with an operator and right operand.
Definition PAst.hpp:185
optoken operator_
The binary operator (+, -, *, /)
Definition PAst.hpp:186
operand operand_
The right-hand operand.
Definition PAst.hpp:187
Represents a power operation.
Definition PAst.hpp:221
expression base
The base expression.
Definition PAst.hpp:222
expression pow
The exponent expression.
Definition PAst.hpp:223
Represents a unary operation applied to an operand.
Definition PAst.hpp:173
operand operand_
The operand the operator is applied to.
Definition PAst.hpp:175
optoken operator_
The unary operator (positive or negative)
Definition PAst.hpp:174
Represents a variable declaration with optional initialization.
Definition PAst.hpp:247
variable lhs
The variable being declared.
Definition PAst.hpp:248
boost::optional< expression > rhs
Optional initialization expression.
Definition PAst.hpp:249
Represents a variable in an expression.
Definition PAst.hpp:139
std::string name
Variable name without the '$' prefix.
Definition PAst.hpp:145
unsigned int find_var(std::string const &name)
Finds a variable index by name.
Definition PProgram.cpp:665
std::vector< double > operator()(ast::nil)
Evaluates a nil node (should never be called).
Definition PProgram.cpp:338
void print_result()
Prints all variable results to standard output (debugging).
Definition PProgram.cpp:701
std::vector< PVarHandler > fVariable
Variable table with values and errors.
Definition PProgram.hpp:448
PVarHandler getVar(const std::string name, bool &ok)
Retrieves a variable by name after evaluation.
Definition PProgram.cpp:685
bool find_var(std::string const &name)
Checks if a variable exists in the symbol table.
Definition PProgram.cpp:285
std::vector< PVarHandler > fVariable
Symbol table of declared variables.
Definition PProgram.hpp:314
std::string pos_to_var(std::string const &name, bool &ok)
Converts position-based variable reference to variable name.
Definition PProgram.cpp:313
void add_predef_var_values(const std::string &name, std::vector< double > &val, std::vector< double > &err)
Injects predefined variable values from collection data.
Definition PProgram.cpp:261
std::map< int, std::string > fVarPos
Map from position index to variable name.
Definition PProgram.hpp:315
boost::function< void(int tag, std::string const &what)> error_handler
Error handler function for reporting semantic errors.
Definition PProgram.hpp:319
void add_var(std::string const &name)
Adds a variable to the symbol table.
Definition PProgram.cpp:275
bool operator()(ast::nil)
Visitor for nil AST nodes (should never be called).
Definition PProgram.hpp:187