It isn't clear to me what your gripe with (recursive) variants are, but here is a variation that goes along with your wish to use 'old fashioned' tree building using dynamically allocated nodes:
- http://liveworkspace.org/code/3VS77n$0
I have purposefully sidestepped the issue of operator precedence in your grammar because
Note how I
- removed ubiquitous memory leaks by using shared_ptr (you can use the Boost one if you don't have a TR1 library)
- I removed the misguided reuse of a specific BinaryExpression instance as a phoenix lazy actor. Instead I made a local
makebinary actor now.
Note how chains of operators (1+2+5+6-10) are now supported:
additive_expr =
primary_expr [ _val = _1 ]
>> *(char_("-+*/") >> primary_expr) [ _val = makebinary(_1, _val, _2)]
;
I added {var}, /, * and (expr) support
added serialization for display (Print virtual method, operator<<) (for display convenience, BinaryExpression stores the operator instead of the resultant method now)
- Therefore now you can use BOOST_SPIRIT_DEBUG (uncomment first line)
- I have renamed
Expression to AbstractExpression (and made de constructor protected)
- I have renamed
PrimaryExpression to Expression (and this is now your main expression datatype)
- I show how to store simplistically variables in a
static map
- be sure to have a look at
qi::symbols and
- e.g. How to add qi::symbols in grammar?
- Uses far less fusion struct adaptation (only for
variable now)
Uses the templated constructor trick to make it very easy to construct an expression from disparate parsed types:
struct Expression : AbstractExpression {
template
Expression(E const& e) : _e(make_from(e)) { } // cloning the expression
// ...
};
is enough to efficiently support e.g.:
primary_expr =
( '(' > expression > ')' ) [ _val = _1 ]
| constant [ _val = _1 ]
| variable [ _val = _1 ]
;
for fun have included a few more test cases:
Input: 3*8 + 6
Expression: Expression(BinaryExpression(BinaryExpression(ConstantExpression(3) * ConstantExpression(8)) + ConstantExpression(6)))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 30
----------------------------------------
Input: 3*(8+6)
Expression: Expression(BinaryExpression(ConstantExpression(3) * BinaryExpression(ConstantExpression(8) + ConstantExpression(6))))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 42
----------------------------------------
Input: 0x1b
Expression: Expression(ConstantExpression(27))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 27
----------------------------------------
Input: 1/3
Expression: Expression(BinaryExpression(ConstantExpression(1) / ConstantExpression(3)))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 0.333333
----------------------------------------
Input: .3333 * 8e12
Expression: Expression(BinaryExpression(ConstantExpression(0.3333) * ConstantExpression(8e+12)))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 2.6664e+12
----------------------------------------
Input: (2 * a) + b
Expression: Expression(BinaryExpression(BinaryExpression(ConstantExpression(2) * VariableExpression('a')) + VariableExpression('b')))
Parse success: true
Remaining unparsed: ''
(a, b): 10, 7
Evaluation result: 27
----------------------------------------
Input: (2 * a) + b
Expression: Expression(BinaryExpression(BinaryExpression(ConstantExpression(2) * VariableExpression('a')) + VariableExpression('b')))
Parse success: true
Remaining unparsed: ''
(a, b): -10, 800
Evaluation result: 780
----------------------------------------
Input: (2 * {a}) + b
Expression: Expression(BinaryExpression(BinaryExpression(ConstantExpression(2) * VariableExpression('a')) + VariableExpression('b')))
Parse success: true
Remaining unparsed: ''
(a, b): -10, 800
Evaluation result: 780
----------------------------------------
Input: {names with spaces}
Expression: Expression(VariableExpression('names with spaces'))
Parse success: true
Remaining unparsed: ''
(a, b): 0, 0
Evaluation result: 0
----------------------------------------
Full Code
// #define BOOST_SPIRIT_DEBUG
// #define BOOST_RESULT_OF_USE_DECLTYPE
// #define BOOST_SPIRIT_USE_PHOENIX_V3
#include
#include
#include
#include