History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: ANTLR-193
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Minor Minor
Assignee: Terence Parr
Reporter: Terence Parr
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
ANTLR v3

add error node to AST upon syntax error

Created: 08/Nov/07 11:48 AM   Updated: 12/Jan/08 02:46 PM
Component/s: All targets
Affects Version/s: 3.0.1
Fix Version/s: 3.1


 Description  « Hide
What happens during AST construction when we get an error? Currently bad tree is created for auto construction and possibly an exception or even infinite loop for rewrite rules.

Try turning off auto insert/delete; let it throw exception during AST ctor. Then, any rule with exception returns error node. Just can't trust any of its structure. Same is true for auto vs manual. So you'd get A ERROR B and C ERROR E if error in b and d. Errors in 'a' and c would give single ERROR node.

Ack: We have to turn off in-rule recovery completely in presence of AST construction regardless of any new ERROR node insertion.

/* Manual AST construction via rewrite rules (simplified)
a : A b C -> A b C ;
b : B ;
*/
try {
A1=input.LT(1); match(input,A,FOLLOW_A_in_a16); stream_A.add(A1);

b2=b(); stream_b.add(b2.getTree());

C3=input.LT(1); match(input,C,FOLLOW_C_in_a20); stream_C.add(C3);

// 3:11: -> A b C
root_0 = (Object)adaptor.nil();
adaptor.addChild(root_0, stream_A.nextNode());
adaptor.addChild(root_0, stream_b.nextTree());
adaptor.addChild(root_0, stream_C.nextNode());

retval.tree = (Object)adaptor.rulePostProcessing(root_0);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
}

/* Auto AST construction (simplified)
c : C d E ;
d : D ;
*/
try {
root_0 = (Object)adaptor.nil();

C5=input.LT(1);
match(input,C,FOLLOW_C_in_c45);
C5_tree = adaptor.create(C5);
adaptor.addChild(root_0, C5_tree);

d6=d(); adaptor.addChild(root_0, d6.getTree());

E7=(input.LT(1);
match(input,E,FOLLOW_E_in_c49);
E7_tree = adaptor.create(E7);
adaptor.addChild(root_0, E7_tree);

retval.tree = adaptor.rulePostProcessing(root_0);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
}

Basically, I think that the best we can do reasonably is to return an ERROR node for an entire rule that gets an error. So for FOR loop:

forDecl : 'for' '(' decl ';' expr ';' expr ')' stat ;

we will still create a valid forDecl tree even with errors in decl or expr, but the subtree would be an ERROR node for those invoked rules that fail. If we miss a token inside forDecl proper, entire result is ERROR. Not optimal, but I'm pretty sure recovering within a rule would be very messy. If fact, my guess we have to turn off in-rule recovery completely in presence of AST regardless of any new ERROR node insertion.

Sounds like the approach of recovering, but bailing out of any rule that catches an error is ok.

Impl: I guess we'd ask the TreeAdaptor to return an error node based upon the current token. One outstanding issue in my head is how to record in that tree node how far ahead the parser had to go before resynchronizing properly. I know how much that particular rule (with error) consumes during recovery, but true "i'm ok" signal is when a valid token match occurs.

 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Terence Parr - 12/Jan/08 11:59 AM
This morning I figured out the solution. added as an improvement for later: ANTLR-213.

Terence Parr - 12/Jan/08 02:46 PM
 added an illustration of the new error node functionality:

http://www.antlr.org/wiki/display/ANTLR3/Tree+construction