Revision 568589
Go back to digest for 6th August 2006Features in Development Tools
Implement backtracking for kdevelop-pg.
(Also known as LL(k) for poor people ;)
The new backtracking construct "try/rollback" is able
to replace all your hand-adapted lookahead hacks.
Use it for conflicts that require arbitrary-length LL(k) lookahead.
Don't use it when you can determine the upcoming rule with
simple [: LA(2).kind == Token_BLAH :] checks.
Old solution
(with lookahead_is_conflicting_item_1() being defined somewhere else):
(
[: lookahead_is_conflicting_item_1() == true :]
var1=conflicting_item_1
|
var2=conflicting_item_2
)
New solution:
try/rollback(var1=conflicting_item_1) catch(var2=conflicting_item_2)
It works this way:
- try to derive conflicting_item_1
- if there are no parsing errors, proceed.
- if there are any errors, go back to the token where
conflicting_item_1 started, and derive conflicting_item_2.
On errors, conflicting_item_1 is not assigned to var1.
Note that if you have multiple annotated items inside the try block
("try/rollback(var1=item1 var2=item2) catch(...)")
and there are parsing errors in item2, then the item1 node is still
assigned to var1. So, it's best to only have single items inside
a try block.
This commit also renames recover(...) to try/recover(...),
as there are many similarities to try/rollback.
If the grammar is using either try/recover or try/rollback constructs,
you now have to provide custom stuff for parser state management:
- a struct named parser_state containing all the variables
that may change during parsing. (It can also be an empty struct.)
- two parser class methods:
* copy_current_state() returns a new parser_state object, or 0
* restore_state() restores the variables in the given
parser_state object back to the parser class.
This is required for a clean rollback or recovery, for parsers
that change some state variables in code segments.
(Like the ltCounter variable in the Java and C# parser.)
Also, the yy_expected_token() and yy_expected_symbol() methods
must now return void instead of bool.
Sorry for the long commit message :]
File Changes
- /branches/work/kdevelop-pg/src
- /kdev-pg-ast.h
- /kdev-pg-clone-tree.cpp
- /kdev-pg-clone-tree.h
- /kdev-pg-code-gen.cpp
- /kdev-pg-code-gen.h
- /kdev-pg-default-visitor.cpp
- /kdev-pg-default-visitor.h
- /kdev-pg-first.cpp
- /kdev-pg-first.h
- /kdev-pg-follow.cpp
- /kdev-pg-follow.h
- /kdev-pg-lexer.ll
- /kdev-pg-parser.yy
- /kdev-pg-pretty-printer.cpp
- /kdev-pg-pretty-printer.h
- /kdev-pg-visitor.cpp
- /kdev-pg-visitor.h
- /kdev-pg.cpp
- /kdev-pg.h