-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
X3: Support recursive rules that modify the context #237
base: develop
Are you sure you want to change the base?
X3: Support recursive rules that modify the context #237
Conversation
make_context() always pushed a new node to the context list when the context is modified (e.g. for "with", "skip" or "no_skip" directives). If such directives are used in recursive rules, this leads to an infinite loop of template instantiations, effectively limiting the use of recursive rules in x3. To fix this, we first check if the tag for the new node is already contained in the context. If we find the tag, we remove the corresponding existing node from the context before pushing the new node with the requested tag. In order to remove a context entry, we have to rebuild all context nodes up to this entry. We can reuse (i.e. link to) the tail of the old context after this entry. In order to resolve life-time issues of newly created context nodes we added an aggregating implementation of struct context.
Nice catch! Seems you have good familiarity with X3! |
I assume all tests pass? |
Yes, all X3 tests pass (at least using msvc-14.1). |
What is the compile-time cost? The paragraph in your 1st comment which starts with: To fix this, and the following paragraph worry me that compile times will suffer. Are there any Also, a test case demonstrating the problem, but simpler, if possible, than https://github.com/cppljevans/spirit/blob/get_rhs/workbench/x3/HanWang_make_context/main.orig.cpp would be helpful in guarding against the problem occurring again, and would give An even better test is: It's better because it detects that the solution in the get_rhs fork when: -DBOOST_SPIRIT_X3_EXPERIMENTAL_SKIP_MAKE_UNIQUE=1 fails but with this pull_request, it succeeds. An even better test is:
With this test, the get_rhs fork fails at compile time instead An even better (because it's shorter) test is: auto const com0 = z3::lit(":0") | z3::space;
z3::rule< lsti<0> > const lst0;
auto const lst0_def
= z3::lit("a")
>>
( z3::lit(",")
>> lst0
| z3::lit(";0")
>> z3::skip(com0)[lst0]
| z3::lit(".")
)
;
BOOST_SPIRIT_DEFINE
( lst0
) The following location for the test looks good to me: https://github.com/boostorg/spirit/blob/develop/test/x3/skip.cpp#L36 What about that, Joel? |
main.altcommit.cpp for problem discussed here: https://sourceforge.net/p/spirit/mailman/message/35963822 with current code in the get_rhs fork, it fails. However, when run with the pull_request here: boostorg#237 it passes. Hence, this test case would filter out the incorrect sollution in this get_rhs branch.
incorrect get_rhs fork and the "more" correct togermer pull request (boostorg#237).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on those life-time issues?
are the new files. These illustrate an alternative to: boostorg#237 This alternative is simpler to understand, OTOH, it requires changing the parser::parse interface from one taking iterator's for args 1 and 2 to one scanner arg (which aggregates the 2 iterators). This scanner arg also contains a skipper. This is in contrast to the pull/237 where the skipper is stored in the context arg (another arg to the parse function). Advantages of this alternative approach are outlined in comments near beginnning of the y3-scanner.hpp file. The test driver is in inf_skipper_context.cpp.
skip.hpp ../support/context.hpp In these files, rm'ed the erroneous patch for solving problem which this PR correctly solves: boostorg#237
make_context() always pushed a new node to the context list when the context is modified (e.g., for "with", "skip", or "no_skip" directives). If such directives are used in recursive rules, this leads to an infinite loop of template instantiations, effectively limiting the use of recursive rules in x3.
To fix this, we first check if the tag for the new node is already contained in the context. If we find the tag, we remove the corresponding existing node from the context before pushing the new node with the requested tag.
In order to remove a context entry, we have to rebuild all context nodes up to this entry. We can reuse (i.e. link to) the tail of the old context after this entry.
In order to resolve life-time issues of newly created context nodes we added an aggregating implementation of struct context.