[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-patch] Applied Patch - Parser robustness improvements
|
Fixed infinite loop problems in the parser by making the end
of file condition a parser backtrack exception instead of a token.
Doug Schaefer
Senior
Staff Software Engineer
Rational Software - IBM Software Group
Ottawa (Kanata), Ontario, Canada
|
Index: parser/ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/ChangeLog,v
retrieving revision 1.3
diff -u -r1.3 ChangeLog
--- parser/ChangeLog 17 Mar 2003 15:22:05 -0000 1.3
+++ parser/ChangeLog 17 Mar 2003 19:22:06 -0000
@@ -1,3 +1,7 @@
+2003-03-17 Doug Schaefer
+ Changed EOF to be a Backtrack exception instead of a token so simplify
+ error handling.
+
2003-03-13 John Camelon
Moved ## token to IScanner from Scanner.
Updated IParserCallback and implementations to deal with Elaborated Type Specifiers.
Index: parser/org/eclipse/cdt/internal/core/parser/IScanner.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScanner.java,v
retrieving revision 1.3
diff -u -r1.3 IScanner.java
--- parser/org/eclipse/cdt/internal/core/parser/IScanner.java 17 Mar 2003 15:22:05 -0000 1.3
+++ parser/org/eclipse/cdt/internal/core/parser/IScanner.java 17 Mar 2003 19:22:06 -0000
@@ -26,7 +26,7 @@
public void addIncludePath(String includePath);
public void overwriteIncludePath( List newIncludePaths );
- public Token nextToken() throws ScannerException;
+ public Token nextToken() throws ScannerException, Parser.EndOfFile;
public void setQuickScan(boolean qs);
public void setCallback(IParserCallback c);
Index: parser/org/eclipse/cdt/internal/core/parser/Parser.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java,v
retrieving revision 1.9
diff -u -r1.9 Parser.java
--- parser/org/eclipse/cdt/internal/core/parser/Parser.java 17 Mar 2003 15:22:05 -0000 1.9
+++ parser/org/eclipse/cdt/internal/core/parser/Parser.java 17 Mar 2003 19:22:07 -0000
@@ -32,7 +32,6 @@
quickParse = quick;
scanner.setQuickScan(quick);
scanner.setCallback(c);
- //fetchToken();
}
public Parser(IScanner s, IParserCallback c) throws Exception {
@@ -78,13 +77,16 @@
public void translationUnit() throws Exception {
Object translationUnit = callback.translationUnitBegin();
Token lastBacktrack = null;
- Token lastToken = null;
- while (LT(1) != Token.tEOF) {
+ Token lastToken;
+ while (true) {
try {
- lastToken = currToken;
+ lastToken = LA(1);
declaration( translationUnit );
- if( currToken == lastToken )
+ if( LA(1) == lastToken )
consumeToNextSemicolon();
+ } catch (EndOfFile e) {
+ // Good
+ break;
} catch (Backtrack b) {
// Mark as failure and try to reach a recovery point
parsePassed = false;
@@ -102,12 +104,11 @@
callback.translationUnitEnd(translationUnit);
}
- protected void consumeToNextSemicolon() {
- for (int t = LT(1); t != Token.tEOF; t = LT(1)) {
+ protected void consumeToNextSemicolon() throws EndOfFile {
+ consume();
+ // TODO - we should really check for matching braces too
+ while (LT(1) != Token.tSEMI) {
consume();
- // TO DO: we should really check for matching braces too
- if (t == Token.tSEMI)
- break;
}
}
@@ -205,9 +206,7 @@
// and look for the left brace;
consume();
while (LT(1) != Token.tLBRACE) {
- if (consume().getType() == Token.tEOF)
- // Oops, couldn't find it
- throw backtrack;
+ consume();
}
// Falling through on purpose
case Token.tLBRACE:
@@ -225,9 +224,6 @@
case Token.tLBRACE:
++depth;
break;
- case Token.tEOF:
- // Oops, no match
- throw backtrack;
}
}
} else {
@@ -461,9 +457,6 @@
case Token.tLBRACE:
++depth;
break;
- case Token.tEOF:
- // Oops, no match
- throw backtrack;
}
}
}
@@ -529,6 +522,7 @@
// parameterDeclarationClause
Object clause = callback.argumentsBegin(declarator);
consume();
+ boolean seenParameter = false;
parameterDeclarationLoop:
for (;;) {
switch (LT(1)) {
@@ -540,9 +534,13 @@
break;
case Token.tCOMMA:
consume();
+ seenParameter = false;
break;
default:
- parameterDeclaration( clause );
+ if (seenParameter)
+ throw backtrack;
+ parameterDeclaration( clause );
+ seenParameter = true;
}
}
callback.argumentsEnd(clause);
@@ -633,9 +631,6 @@
case Token.tLBRACE:
++depth;
break;
- case Token.tEOF:
- // Oops, no match
- throw backtrack;
}
}
}
@@ -1362,24 +1357,32 @@
}
// Backtracking
- private static class Backtrack extends Exception {
+ public static class Backtrack extends Exception {
}
private static Backtrack backtrack = new Backtrack();
+ // End of file generally causes backtracking
+ public static class EndOfFile extends Backtrack {
+ }
+
+ public static EndOfFile endOfFile = new EndOfFile();
+
// Token management
private IScanner scanner;
private Token currToken;
- private Token fetchToken() {
+ private Token fetchToken() throws EndOfFile {
try {
return scanner.nextToken();
+ } catch (EndOfFile e) {
+ throw e;
} catch (Exception e) {
return null;
}
}
- protected Token LA(int i) {
+ protected Token LA(int i) throws EndOfFile {
if (i < 1)
// can't go backwards
return null;
@@ -1390,34 +1393,37 @@
Token retToken = currToken;
for (; i > 1; --i) {
- if (retToken.getNext() == null)
- fetchToken();
retToken = retToken.getNext();
+ if (retToken == null)
+ retToken = fetchToken();
}
return retToken;
}
- protected int LT(int i) {
+ protected int LT(int i) throws EndOfFile {
return LA(i).type;
}
- protected Token consume() {
- if (currToken.getNext() == null)
- fetchToken();
+ protected Token consume() throws EndOfFile {
+ if (currToken == null)
+ currToken = fetchToken();
+
Token retToken = currToken;
currToken = currToken.getNext();
return retToken;
}
- protected Token consume(int type) throws Exception {
+ protected Token consume(int type) throws Backtrack {
if (LT(1) == type)
return consume();
else
throw backtrack;
}
- protected Token mark() {
+ protected Token mark() throws EndOfFile {
+ if (currToken == null)
+ currToken = fetchToken();
return currToken;
}
Index: parser/org/eclipse/cdt/internal/core/parser/Scanner.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java,v
retrieving revision 1.5
diff -u -r1.5 Scanner.java
--- parser/org/eclipse/cdt/internal/core/parser/Scanner.java 17 Mar 2003 15:22:05 -0000 1.5
+++ parser/org/eclipse/cdt/internal/core/parser/Scanner.java 17 Mar 2003 19:22:08 -0000
@@ -366,6 +366,9 @@
private int getChar() {
int c = NOCHAR;
+ if (currentContext == null)
+ // past the end of file
+ return c;
boolean done;
do {
@@ -436,12 +439,12 @@
- public Token nextToken() throws ScannerException {
+ public Token nextToken() throws ScannerException, Parser.EndOfFile {
return nextToken( true );
}
- protected Token nextToken( boolean pasting ) throws ScannerException
+ protected Token nextToken( boolean pasting ) throws ScannerException, Parser.EndOfFile
{
count++;
@@ -1102,10 +1105,9 @@
break;
}
- return newToken(
- Token.tEOF,
- "Bad Char: " + (char) c,
- currentContext);
+ // Bad character
+ // TODO - does this need it's own exception
+ throw Parser.endOfFile;
}
}
@@ -1113,9 +1115,7 @@
throw new ScannerException("End of file encountered without terminating #endif");
// we're done
- if (currentToken != null)
- currentToken.setNext(Token.EOF);
- return Token.EOF;
+ throw Parser.endOfFile;
}
static {
@@ -1254,7 +1254,8 @@
ExpressionEvaluator evaluator = new ExpressionEvaluator();
Scanner trial =
new Scanner(
- new StringReader(expression),
+ // Semicolon makes this valid C (hopefully)
+ new StringReader(expression + ";"),
EXPRESSION,
definitions);
Parser parser = new Parser(trial, evaluator);
@@ -1373,7 +1374,7 @@
handleInclusion(f.trim(), useIncludePath );
}
- protected void poundDefine() throws ScannerException {
+ protected void poundDefine() throws ScannerException, Parser.EndOfFile {
skipOverWhitespace();
// definition
String key = getNextIdentifier();
@@ -1424,9 +1425,13 @@
null);
Token t = helperScanner.nextToken(false);
- while (t.type != Token.tEOF) {
- macroReplacementTokens.add(t);
- t = helperScanner.nextToken(false);
+ try {
+ while (true) {
+ macroReplacementTokens.add(t);
+ t = helperScanner.nextToken(false);
+ }
+ } catch (Parser.EndOfFile e) {
+ // Good
}
IMacroDescriptor descriptor = new MacroDescriptor();
Index: parser/org/eclipse/cdt/internal/core/parser/Token.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java,v
retrieving revision 1.3
diff -u -r1.3 Token.java
--- parser/org/eclipse/cdt/internal/core/parser/Token.java 11 Mar 2003 02:42:47 -0000 1.3
+++ parser/org/eclipse/cdt/internal/core/parser/Token.java 17 Mar 2003 19:22:09 -0000
@@ -24,8 +24,6 @@
image = i;
}
- public static Token EOF = new Token(Token.tEOF, "<EOF>");
-
public String toString()
{
return "Token type=" + type + " image =" + image + " offset=" + offset;
@@ -47,7 +45,6 @@
public void setNext(Token t) { next = t; }
// Token types
- static public final int tEOF = 0;
static public final int tIDENTIFIER = 1;
static public final int tINTEGER = 2;
static public final int tCOLONCOLON = 3;
Index: parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java,v
retrieving revision 1.2
diff -u -r1.2 ExprEvalTest.java
--- parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java 4 Mar 2003 18:25:45 -0000 1.2
+++ parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java 17 Mar 2003 19:22:38 -0000
@@ -25,17 +25,17 @@
}
public void testInteger() throws Exception {
- runTest("5", 5);
+ runTest("5;", 5);
}
public void testRelational() throws Exception {
- runTest("1 < 2", 1);
- runTest("2 < 1", 0);
- runTest("2 == 1 + 1", 1);
- runTest("2 != 1 + 1", 0);
+ runTest("1 < 2;", 1);
+ runTest("2 < 1;", 0);
+ runTest("2 == 1 + 1;", 1);
+ runTest("2 != 1 + 1;", 0);
}
public void testBracketed() throws Exception {
- runTest("2 * (3 + 4)", 14);
+ runTest("2 * (3 + 4);", 14);
}
}
Index: parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java,v
retrieving revision 1.5
diff -u -r1.5 ScannerTestCase.java
--- parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java 11 Mar 2003 02:42:43 -0000 1.5
+++ parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java 17 Mar 2003 19:22:39 -0000
@@ -8,6 +8,7 @@
import junit.framework.TestSuite;
import org.eclipse.cdt.internal.core.parser.IMacroDescriptor;
+import org.eclipse.cdt.internal.core.parser.Parser;
import org.eclipse.cdt.internal.core.parser.Scanner;
import org.eclipse.cdt.internal.core.parser.ScannerException;
import org.eclipse.cdt.internal.core.parser.Token;
@@ -176,16 +177,19 @@
try
{
Token t= scanner.nextToken();
- while ((t != null) && (t.type != Token.tEOF))
+ while (t != null)
{
if (verbose)
System.out.println("Token t = " + t);
- if ((t.type < Token.tEOF) || (t.type > Token.tLAST))
+ if ((t.type < 1) || (t.type > Token.tLAST))
System.out.println("Unknown type for token " + t);
t= scanner.nextToken();
}
}
+ catch (Parser.EndOfFile e)
+ {
+ }
catch (ScannerException se)
{
throw se;
@@ -245,7 +249,7 @@
validateToken(Token.tASSIGN);
validateInteger("5");
validateToken(Token.tSEMI);
- validateToken(Token.tEOF);
+ validateEOF();
// the case we were failing against in ctype.h
// this is a definition, not a macro!
@@ -445,7 +449,7 @@
validateEOF();
initializeScanner("#define SYMBOL 5\n#ifndef SYMBOL\nint counter(SYMBOL);\n#endif");
- validateToken(Token.tEOF);
+ validateEOF();
initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
validateToken(Token.t_int);
@@ -522,7 +526,7 @@
validateBalance();
initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
- validateToken(Token.tEOF);
+ validateEOF();
validateBalance();
validateDefinition("FOO", "4");
@@ -833,7 +837,7 @@
}
}
- public void testQuickScan()
+ public void testQuickScan() throws Parser.EndOfFile
{
try
{
@@ -970,29 +974,45 @@
public void validateIdentifier(String expectedImage) throws ScannerException
{
- Token t= scanner.nextToken();
- assertTrue(t.type == Token.tIDENTIFIER);
- assertTrue(t.image.equals(expectedImage));
+ try {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tIDENTIFIER);
+ assertTrue(t.image.equals(expectedImage));
+ } catch (Parser.EndOfFile e) {
+ assertTrue(false);
+ }
}
public void validateInteger(String expectedImage) throws ScannerException
{
- Token t= scanner.nextToken();
- assertTrue(t.type == Token.tINTEGER);
- assertTrue(t.image.equals(expectedImage));
+ try {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tINTEGER);
+ assertTrue(t.image.equals(expectedImage));
+ } catch (Parser.EndOfFile e) {
+ assertTrue(false);
+ }
}
public void validateString(String expectedImage) throws ScannerException
{
- Token t= scanner.nextToken();
- assertTrue(t.type == Token.tSTRING);
- assertTrue(t.image.equals(expectedImage));
+ try {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tSTRING);
+ assertTrue(t.image.equals(expectedImage));
+ } catch (Parser.EndOfFile e) {
+ assertTrue(false);
+ }
}
public void validateToken(int tokenType) throws ScannerException
{
- Token t= scanner.nextToken();
- assertTrue(t.type == tokenType);
+ try {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == tokenType);
+ } catch (Parser.EndOfFile e) {
+ assertTrue(false);
+ }
}
public void validateBalance(int expected)
@@ -1007,7 +1027,10 @@
public void validateEOF() throws ScannerException
{
- validateToken(Token.tEOF);
+ try {
+ assertNull(scanner.nextToken());
+ } catch (Parser.EndOfFile e) {
+ }
}
public void validateDefinition(String name, String value)
@@ -1022,7 +1045,7 @@
{
String definition= null;
definition= (String) scanner.getDefinition(name);
- this.assertNotNull(definition);
+ assertNotNull(definition);
int intValue= (Integer.valueOf((String) definition)).intValue();
assertEquals(value, intValue);
}
@@ -1105,7 +1128,7 @@
validateInteger( "0");
validateToken( Token.tSEMI );
validateToken( Token.tRBRACE );
- validateToken( Token.tEOF );
+ validateEOF();
}
} catch( ScannerException se )
{