Improve error handling for single-token productions

This commit is contained in:
Ben Gruver 2015-01-30 18:46:11 -08:00
parent 7e6f050bac
commit 3b7332192b
8 changed files with 118 additions and 16 deletions

View File

@ -148,6 +148,14 @@ import javax.annotation.Nullable;
} }
} }
public void finishToken(Marker marker, IElementType elementType) {
if (state.errorRecovery) {
marker.drop();
} else {
marker.done(elementType);
}
}
@Override @Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) { public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
displayRecognitionError(mark(), tokenNames, e); displayRecognitionError(mark(), tokenNames, e);
@ -370,7 +378,7 @@ member_name
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: (simple_name : (simple_name
| MEMBER_NAME) | MEMBER_NAME)
{ marker.done(SmaliElementTypes.MEMBER_NAME); }; { finishToken(marker, SmaliElementTypes.MEMBER_NAME); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -427,7 +435,7 @@ param_list_reference
primitive_type primitive_type
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: PRIMITIVE_TYPE : PRIMITIVE_TYPE
{ marker.done(SmaliElementTypes.PRIMITIVE_TYPE); }; { finishToken(marker, SmaliElementTypes.PRIMITIVE_TYPE); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -436,7 +444,7 @@ primitive_type
class_descriptor class_descriptor
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: CLASS_DESCRIPTOR : CLASS_DESCRIPTOR
{ marker.done(SmaliElementTypes.CLASS_TYPE); }; { finishToken(marker, SmaliElementTypes.CLASS_TYPE); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -445,7 +453,7 @@ class_descriptor
array_descriptor array_descriptor
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ARRAY_TYPE_PREFIX (primitive_type | class_descriptor) : ARRAY_TYPE_PREFIX (primitive_type | class_descriptor)
{ marker.done(SmaliElementTypes.ARRAY_TYPE); }; { finishToken(marker, SmaliElementTypes.ARRAY_TYPE); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -454,7 +462,7 @@ array_descriptor
void_type void_type
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: VOID_TYPE : VOID_TYPE
{ marker.done(SmaliElementTypes.VOID_TYPE); }; { finishToken(marker, SmaliElementTypes.VOID_TYPE); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -478,7 +486,7 @@ reference_type_descriptor
null_literal null_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: NULL_LITERAL : NULL_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -487,7 +495,7 @@ null_literal
bool_literal bool_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: BOOL_LITERAL : BOOL_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -496,7 +504,7 @@ bool_literal
byte_literal byte_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: BYTE_LITERAL : BYTE_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -505,7 +513,7 @@ byte_literal
char_literal char_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: CHAR_LITERAL : CHAR_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -514,7 +522,7 @@ char_literal
short_literal short_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: SHORT_LITERAL : SHORT_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -524,7 +532,7 @@ integer_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ( POSITIVE_INTEGER_LITERAL : ( POSITIVE_INTEGER_LITERAL
| NEGATIVE_INTEGER_LITERAL) | NEGATIVE_INTEGER_LITERAL)
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -533,7 +541,7 @@ integer_literal
long_literal long_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: LONG_LITERAL : LONG_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -543,7 +551,7 @@ float_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ( FLOAT_LITERAL_OR_ID : ( FLOAT_LITERAL_OR_ID
| FLOAT_LITERAL ) | FLOAT_LITERAL )
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -553,7 +561,7 @@ double_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ( DOUBLE_LITERAL_OR_ID : ( DOUBLE_LITERAL_OR_ID
| DOUBLE_LITERAL) | DOUBLE_LITERAL)
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -562,7 +570,7 @@ double_literal
string_literal string_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: STRING_LITERAL : STRING_LITERAL
{ marker.done(SmaliElementTypes.LITERAL); }; { finishToken(marker, SmaliElementTypes.LITERAL); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);
@ -586,6 +594,7 @@ enum_literal
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
type_field_method_literal type_field_method_literal
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: ( reference_type_descriptor : ( reference_type_descriptor
@ -603,6 +612,7 @@ type_field_method_literal
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
subannotation subannotation
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: SUBANNOTATION_DIRECTIVE class_descriptor annotation_element* END_SUBANNOTATION_DIRECTIVE : SUBANNOTATION_DIRECTIVE class_descriptor annotation_element* END_SUBANNOTATION_DIRECTIVE
@ -683,6 +693,7 @@ annotation
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
fully_qualified_method fully_qualified_method
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: reference_type_descriptor ARROW member_name method_prototype_reference : reference_type_descriptor ARROW member_name method_prototype_reference
@ -692,6 +703,7 @@ fully_qualified_method
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
fully_qualified_field fully_qualified_field
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: reference_type_descriptor ARROW member_name COLON nonvoid_type_descriptor : reference_type_descriptor ARROW member_name COLON nonvoid_type_descriptor
@ -701,6 +713,7 @@ fully_qualified_field
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
label label
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: COLON simple_name : COLON simple_name
@ -710,6 +723,7 @@ label
reportError(marker, re, false); reportError(marker, re, false);
} }
// TODO: check missing initial token
label_ref label_ref
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: COLON simple_name : COLON simple_name
@ -774,7 +788,7 @@ parameter_directive
register register
@init { Marker marker = mark(); } @init { Marker marker = mark(); }
: REGISTER : REGISTER
{ marker.done(SmaliElementTypes.REGISTER_REFERENCE); }; { finishToken(marker, SmaliElementTypes.REGISTER_REFERENCE); };
catch [RecognitionException re] { catch [RecognitionException re] {
recover(input, re); recover(input, re);
reportError(marker, re, false); reportError(marker, re, false);

View File

@ -97,4 +97,7 @@ public class ParserTest extends ParsingTestCase {
public void testEmpty() throws Exception { doTest(true); } public void testEmpty() throws Exception { doTest(true); }
public void testInvalidClassDirective() throws Exception { doTest(true); } public void testInvalidClassDirective() throws Exception { doTest(true); }
public void testInvalidClassDirective2() throws Exception { doTest(true); }
public void testSuperClassInvalidSyntax() throws Exception { doTest(true); }
public void testSuperClassInvalidSyntax2() throws Exception { doTest(true); }
} }

View File

@ -0,0 +1,2 @@
.class
.super Ljava/lang/Object;

View File

@ -0,0 +1,17 @@
smali.FILE
SmaliClass(CLASS)
SmaliModifierList(MODIFIER_LIST)
<empty list>
SmaliExtendsList(EXTENDS_LIST)
<empty list>
SmaliImplementsList(IMPLEMENTS_LIST)
<empty list>
PsiElement(CLASS_STATEMENT)
PsiElement(CLASS_DIRECTIVE)('.class')
PsiWhiteSpace('\n')
PsiElement(ACCESS_LIST)
<empty list>
PsiErrorElement:extraneous input '.super' expecting CLASS_DESCRIPTOR
PsiElement(SUPER_DIRECTIVE)('.super')
PsiWhiteSpace(' ')
PsiElement(CLASS_DESCRIPTOR)('Ljava/lang/Object;')

View File

@ -0,0 +1,2 @@
.class Lblah;
.super

View File

@ -0,0 +1,20 @@
smali.FILE
SmaliClass(CLASS)
SmaliModifierList(MODIFIER_LIST)
<empty list>
SmaliExtendsList(EXTENDS_LIST)
<empty list>
SmaliImplementsList(IMPLEMENTS_LIST)
<empty list>
PsiElement(CLASS_STATEMENT)
PsiElement(CLASS_DIRECTIVE)('.class')
PsiWhiteSpace(' ')
PsiElement(ACCESS_LIST)
<empty list>
PsiElement(CLASS_TYPE)
PsiElement(CLASS_DESCRIPTOR)('Lblah;')
PsiWhiteSpace('\n')
PsiElement(SUPER_STATEMENT)
PsiElement(SUPER_DIRECTIVE)('.super')
PsiErrorElement:mismatched input '<EOF>' expecting CLASS_DESCRIPTOR
<empty list>

View File

@ -0,0 +1,5 @@
.class Lblah;
.super
.method blah()V
.end method

View File

@ -0,0 +1,39 @@
smali.FILE
SmaliClass(CLASS)
SmaliModifierList(MODIFIER_LIST)
<empty list>
SmaliExtendsList(EXTENDS_LIST)
<empty list>
SmaliImplementsList(IMPLEMENTS_LIST)
<empty list>
PsiElement(CLASS_STATEMENT)
PsiElement(CLASS_DIRECTIVE)('.class')
PsiWhiteSpace(' ')
PsiElement(ACCESS_LIST)
<empty list>
PsiElement(CLASS_TYPE)
PsiElement(CLASS_DESCRIPTOR)('Lblah;')
PsiWhiteSpace('\n')
PsiElement(SUPER_STATEMENT)
PsiElement(SUPER_DIRECTIVE)('.super')
PsiErrorElement:missing CLASS_DESCRIPTOR at '.method'
<empty list>
PsiWhiteSpace('\n\n')
SmaliMethod(METHOD)
SmaliModifierList(MODIFIER_LIST)
<empty list>
PsiElement(METHOD_DIRECTIVE)('.method')
PsiWhiteSpace(' ')
PsiElement(ACCESS_LIST)
<empty list>
PsiElement(MEMBER_NAME)
PsiElement(SIMPLE_NAME)('blah')
SmaliMethodPrototype(METHOD_PROTOTYPE)
PsiElement(OPEN_PAREN)('(')
SmaliMethodParamList(METHOD_PARAM_LIST)
<empty list>
PsiElement(CLOSE_PAREN)(')')
PsiElement(VOID_TYPE)
PsiElement(VOID_TYPE)('V')
PsiWhiteSpace('\n')
PsiElement(END_METHOD_DIRECTIVE)('.end method')