Xpressive, symantic actions and combination enumeration
Hi, First let me say. Awesome library and thanks for releasing it to the world. I'm looking for a way to apply all the currently queued semantic actions _without_ turning off backtracking. So, as the manual suggests, keep manages to apply the queued actions but it also turns off backtracking. The reason I am doing this is simple though unusual. I am trying to determine every possible match for a given input sequence, recording and ranking each one individually. A simple (contrived) example would be... input = "abcd"; expression = apply(+alpha[save_lhs(_)] >> +alpha[save_rhs(_)] >> eos) Ideally, applying the expression would yield the following combinations for 'lhs' and 'rhs' 1. "a","bcd" 2. "ab","cd" 3. "abc","d" The best solution I have come up with has an unacceptable time complexity. In short, the solution is to have a match assertion at the end of the expression which only succeeds on the nth try. I then use a while loop, executing regex_match with increasing values of 'n' until no more matches are found. Of course the problem with this solution is that the time complexity goes to n!+(n-1)!+(n-2)!... Any ideas?
Lee Simpson wrote:
Hi,
First let me say. Awesome library and thanks for releasing it to the world.
Thanks!
I'm looking for a way to apply all the currently queued semantic actions _without_ turning off backtracking. So, as the manual suggests, keep manages to apply the queued actions but it also turns off backtracking.
<snip>
Any ideas?
You don't have to turn off backtracking for the whole regex. You can use keep() in a few strategic places within your regex as follows: sregex rx = ... >> keep(nil[ /*semantic action*/ ]) >> ...; "nil" always succeeds and consumes 0 characters. It's a way to cause the semantic action to execute immediately. Would something like that help you? -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler wrote:
Lee Simpson wrote:
Hi,
First let me say. Awesome library and thanks for releasing it to the world.
Thanks!
I'm looking for a way to apply all the currently queued semantic actions _without_ turning off backtracking. So, as the manual suggests, keep manages to apply the queued actions but it also turns off backtracking.
<snip>
Any ideas?
You don't have to turn off backtracking for the whole regex. You can use keep() in a few strategic places within your regex as follows:
sregex rx = ... >> keep(nil[ /*semantic action*/ ]) >> ...;
"nil" always succeeds and consumes 0 characters. It's a way to cause the semantic action to execute immediately. Would something like that help you?
In case I wasn't clear, here is a little program that demonstrates what
I was getting at:
#include <string>
#include <iostream>
#include
That is _exactly_ what I was after! Thanks so much.
On Wed, May 6, 2009 at 3:11 AM, Eric Niebler
Eric Niebler wrote:
Lee Simpson wrote:
Hi,
First let me say. Awesome library and thanks for releasing it to the world.
Thanks!
I'm looking for a way to apply all the currently queued semantic actions
_without_ turning off backtracking. So, as the manual suggests, keep manages to apply the queued actions but it also turns off backtracking.
<snip>
Any ideas?
You don't have to turn off backtracking for the whole regex. You can use keep() in a few strategic places within your regex as follows:
sregex rx = ... >> keep(nil[ /*semantic action*/ ]) >> ...;
"nil" always succeeds and consumes 0 characters. It's a way to cause the semantic action to execute immediately. Would something like that help you?
In case I wasn't clear, here is a little program that demonstrates what I was getting at:
#include <string> #include <iostream> #include
#include using namespace boost::xpressive; int main() { std::string text = "abcd"; sregex rx = // Match some stuff and save some submatches (s1= +alpha) >> (s2= +alpha) >> eos >> // Display the submatches eagerly. keep(nil[ref(std::cout) << s1 << ", " << s2 << "\n"]) >> // Cause the fail and backtrack. ~before(nil);
regex_match(text, rx);
return 0; }
For me, this dispays:
abc, d ab, cd a, bcd
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Damn. I've just implemented the whole algorithm using your suggested approach, and I've come across a problem.I don't have a simple way to describe my dilemma, so a complex way will ave to do :-/ First of, I'll describe the way I have implemented your suggestion. First off, I utilize an expression of the form ((s1 = expr) >> keep(nil[action(_,...)])) for each significant component of the expression. At the very end of the expression I add keep(nil[consolidate_combination(...)])
~before(nil), which ensures that all combinations are tried. Of course, this solution is fundamentally flawed. This is because each action is executed immediately and thus leaves garbage state information around when the expression backtracks and attempts a different match.
I see that your example does not suffer from this flaw since the example
expression is quite linear and does not contain many significant components
(read: captures). Unfortunately, I need to be able to apply this to
arbitrarily complex expressions.
Ideally I would like to add a function which looks like the 'keep' function,
but does not turn off backtracking. Such that i could do something like the
following:
expr = apply( (+alpha)[action_a(_,...)] >> ((+alpha)[action_b(_,...)] |
(+alnum)[action_c(_,...)]) >> eos >> nil[consolidate]) >> ~before(nil);
the idea being that action_a/action_b/action_c store state
information, consolidate
gathers up that state information (resetting it for the next combination)
and apply would execute all the semantic actions currently queued within it.
I have been looking into the implementation details of xpressive and it
seems that what I need to do is somehow apply a slightly modified version of
xpressive::detail::end_matcher to the expression. Of course, I have no idea
how this would best be achieved so I would need your help to do such a
thing.
I hope this description is adequate, but I'm sure it probably not. Let me
know if/where it needs more explaining.
Thanks,
Lee Simpson
On Wed, May 6, 2009 at 1:20 PM, Lee Simpson
wrote:
That is _exactly_ what I was after! Thanks so much.
On Wed, May 6, 2009 at 3:11 AM, Eric Niebler
wrote: Eric Niebler wrote:
Lee Simpson wrote:
Hi,
First let me say. Awesome library and thanks for releasing it to the world.
Thanks!
I'm looking for a way to apply all the currently queued semantic actions
_without_ turning off backtracking. So, as the manual suggests, keep manages to apply the queued actions but it also turns off backtracking.
<snip>
Any ideas?
You don't have to turn off backtracking for the whole regex. You can use keep() in a few strategic places within your regex as follows:
sregex rx = ... >> keep(nil[ /*semantic action*/ ]) >> ...;
"nil" always succeeds and consumes 0 characters. It's a way to cause the semantic action to execute immediately. Would something like that help you?
In case I wasn't clear, here is a little program that demonstrates what I was getting at:
#include <string> #include <iostream> #include
#include using namespace boost::xpressive; int main() { std::string text = "abcd"; sregex rx = // Match some stuff and save some submatches (s1= +alpha) >> (s2= +alpha) >> eos >> // Display the submatches eagerly. keep(nil[ref(std::cout) << s1 << ", " << s2 << "\n"]) >> // Cause the fail and backtrack. ~before(nil);
regex_match(text, rx);
return 0; }
For me, this dispays:
abc, d ab, cd a, bcd
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Lee Simpson wrote:
Damn. I've just implemented the whole algorithm using your suggested approach, and I've come across a problem. I don't have a simple way to describe my dilemma, so a complex way will ave to do :-/
The best way is to post source code.
First of, I'll describe the way I have implemented your suggestion. First off, I utilize an expression of the form ((s1 = expr) >> keep(nil[action(_,...)])) for each significant component of the expression. <snip>
Stop right there. Are you really using nil[action(_,...)] ? In this context, xpressive will replace _ with the submatch corresponding to the subexpression to which the semantic action is attached. In this case, the action is attached to nil, which always matches 0 characters. So your action will always be passed an empty submatch. I bet that's not what you want. Did you intend nil[action(s1,...)] perhaps? -- Eric Niebler BoostPro Computing http://www.boostpro.com
I'll clean up the source and post it soon.
As for using '_' inside a 'nil', err, no i'm not. That was just a typo in my
example, I've been using captures.
On Thu, May 7, 2009 at 2:51 AM, Eric Niebler
Lee Simpson wrote:
Damn. I've just implemented the whole algorithm using your suggested approach, and I've come across a problem. I don't have a simple way to describe my dilemma, so a complex way will ave to do :-/
The best way is to post source code.
First of, I'll describe the way I have implemented your suggestion.
First off, I utilize an expression of the form ((s1 = expr) >> keep(nil[action(_,...)])) for each significant component of the expression.
<snip>
Stop right there. Are you really using nil[action(_,...)] ? In this context, xpressive will replace _ with the submatch corresponding to the subexpression to which the semantic action is attached. In this case, the action is attached to nil, which always matches 0 characters. So your action will always be passed an empty submatch. I bet that's not what you want. Did you intend nil[action(s1,...)] perhaps?
-- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Eric Niebler
-
Lee Simpson